Reputation: 198
So, I'm having this class about catamorphisms and what not, and I need to code the in of a data type.
The data type is
data Expr = Num Int | Bop Expr Op Expr deriving (Eq,Show)
and the function must have this signature
inExpr :: Either Int (Op,(Expr,Expr)) -> Expr
inExpr
should be, I think, something along the lines of
inExpr = Either Num (Bop something)
but I can't figure out the something.
Upvotes: 2
Views: 155
Reputation: 477616
You are quite close. We can in fact easily derive the type of something
by using a "hole" (_
) in ghci
:
Prelude Data.Either> :{
Prelude Data.Either| inExpr :: Either Int (Op,(Expr,Expr)) -> Expr
Prelude Data.Either| inExpr = either Num _
Prelude Data.Either| :}
<interactive>:36:21: error:
• Found hole: _ :: (Op, (Expr, Expr)) -> Expr
• In the second argument of ‘either’, namely ‘_’
In the expression: either Num _
In an equation for ‘inExpr’: inExpr = either Num _
• Relevant bindings include
inExpr :: Either Int (Op, (Expr, Expr)) -> Expr
(bound at <interactive>:36:1)
So we know that this function _
will need to have as type (Op, (Expr, Expr)) -> Expr
.
We can for example use a lambda-expression here:
inExpr :: Either Int (Op,(Expr,Expr)) -> Expr
inExpr = either Num (\(o, (l, r)) -> Bop l o r)
We thus "unpack" the tuple and the subtuple with a (o, (l, r))
pattern, and then construct an Expr
by using the Bop
data constructor, with l
, o
and r
as arguments.
That being said, simple pattern matching, for example in the head of the fucntion, will do the trick as well, and is perhaps easier to understand:
inExpr :: Either Int (Op,(Expr,Expr)) -> Expr
inExpr (Left a) = Num a
inExpr (Right (o, (l, r))) = Bop l o r
Upvotes: 6
Reputation: 7159
Why don't just
inExpr ie = case ie of
Left n -> Num n
Right (o, (e1, e2)) -> Bop e1 o e2
?
Or if you like either
function
inExpr = either Num (\(o, (e1, e2)) -> Bop e1 o e2)
Upvotes: 9