I want to change all literals.
data Expressions a = ListExpression String[Expressions a]
| BinaryExpression String (Expressions a) (Expressions a)
| UnaryExpression String(Expressions a)
| Variables Variable
| Literals a
deriving Eq
Now i want to have all Literals
changed to b
, if the literals in c
equals b
.
So example:
changeData 20 30 (Literals 100) = (Literals 100)
changeData 20 30 (Literals 20) = (Literals 30)
The expression itself should not be changed.
changeData :: (Eq a) => a -> a -> Expressions a -> Expressions a
changeData a b c
I dont understand how to access it. I thought something like this:
fmap (Literals b == Literals a) (\x -> if x == True = a else b)
I thought like: Literals b == Literals a for each Expression. If true, then change to a, otherwise to b.
But like I wrote it down, its not working and I cant figure my mistake out.
Am im fundamentally missunderstanding something?
CodePudding user response:
First, your Functor
instance is making up data constructors, rather than using the ones that were actually defined.
instance Functor Expressions where
fmap f (Literals a) = Literals (f a)
fmap f (Variables a) = Variables a
fmap f (UnaryExpression a b) = UnaryExpression a (fmap f b)
fmap f (BinaryExpression a b c) = BinaryExpression a (fmap f b) (fmap f c)
fmap f (ListExpression a b) = ListExpression a (fmap (fmap f) b)
Next, all you need is a function that checks if its argument is equal to a
: if it is, return b
; otherwise return the argument.
changeData a b c = fmap (\x -> if x == a then b else x) c
The definition of fmap
already handles each of the data constructors for Expression
; the function only needs to worry about the value extracted from a Literals
value. (That is, f
is only ever applied to a value in a Literals
value; otherwise, it is just fmap
ped recursively until it reaches a Literals
.)
CodePudding user response:
You can let Haskell derive the instance for the Functor
typeclass with the DeriveFunctor
GHC extension:
{-# LANGUAGE DeriveFunctor #-}
data Expressions a
= ListExpression String [Expressions a]
| BinaryExpression String (Expressions a) (Expressions a)
| UnaryExpression String (Expressions a)
| Variables Variable
| Literals a
deriving (Eq, Functor)
GHC will generate a Functor
instance where it maps items of type a
to type b
by calling the functor function on these, and it will recurse on expressions with an a
to map the a
items wrapped in these subexpressions.
Then you can use fmap
for changeData
as @chepner says with:
changeData :: Eq a => a -> a -> Expressions a -> Expressions a
changeData a b = fmap (\x -> x == a then b else x)