0

How to get a constructor as a function from the (G)ADT argument in Haskell? Is it possible to do something like this?

data  Ex1 =  C1 Int | C2 Int -- | ..... 
           | C3

fun :: Ex1 -> Ex1
fun C3    = C3
fun (c i) = c $ i^2

It is not appropriate for me to.

fun (C1 i) = C1 $ i^2
fun (C2 i) = C2 $ i^2
Alex K.
  • 93
  • 4
  • 2
    Why is matching on the constructors 'not appropriate'? – Benjamin Hodgson Feb 18 '15 at 22:57
  • Because a lot constructors. I do not want to duplicate the big code. In fact. data AST = Imm Int | Arg Int | Add AST AST | Sub AST AST | Mul AST AST | Div AST AST ...... – Alex K. Feb 18 '15 at 23:14
  • Big data types are something of a code smell. It might be worth trying to simplify the design of your AST. – Benjamin Hodgson Feb 18 '15 at 23:18
  • 2
    To @BenjaminHodgson's point, you can always do something like `data AST = ... | BinOp BinOpType AST AST` with `data BinOpType = Add | Sub | Mul | Div`. – Rein Henrichs Feb 18 '15 at 23:51

1 Answers1

6

If you are ok with changing the type of Ex1 then:

{-# LANGUAGE DeriveFunctor #-}

data  Ex1 a =  C1 a | C2 a
            | C3 deriving (Show, Functor)

fun :: Ex1 Int -> Ex1 Int
fun y = fmap (\x -> x^2) y

Demo in ghci:

λ> fun $ C1 3
C1 9
λ> fun $ C2 3
C2 9
λ> fun C3
C3
Sibi
  • 47,472
  • 16
  • 95
  • 163
  • Thank U. But I'm too simplified real task. In fact. data AST = Imm Int | Arg Int | Add AST AST | Sub AST AST | Mul AST AST | Div AST AST reduce:: (Int->Int->Int) -> AST -> AST reduce f (t a b) = go a b where go (Imm a) (Imm b) = Imm $ f a b go a b = t a b – Alex K. Feb 18 '15 at 23:01
  • 1
    This will still work for your use case with `data AST a = Imm a | Arg Int | Add (AST a) (AST a) | ...`. Then you just need an extra function for `Arg`, assuming that `Imm` is the constructor for values in your expression language and that `Arg` is something else. `Arg a` might work as well, depending on what the constructors represent. – Rein Henrichs Feb 18 '15 at 23:55