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 fmapped 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)
