I have data type of Associative Computations Tree
data EvalATree b a = Leaf a | Node ([b] -> a) [EvalATree b a]
Wrote Functor and Applicative for this type
instance Functor (EvalATree b) where
fmap :: (a -> c) -> EvalATree b a -> EvalATree b c
fmap f (Leaf a) = pure (f a)
fmap f (Node g trees) = Node (f . g) (fmap (fmap f) trees)
instance Applicative (EvalATree b) where
pure :: a -> EvalATree b a
(<*>) :: EvalATree b (a -> c) -> EvalATree b a -> EvalATree b c
(Leaf f) <*> (Leaf x) = fmap f (Leaf x)
(Leaf f) <*> (Node g trees) = Node (f . g) (fmap (fmap f) trees)
(Node g trees) <*> (Leaf x) = Node (g <*> pure x) (fmap (<*> pure x) trees)
(Node g trees) <*> (Node f otherTrees) = Node (g <*> f) (zipWith (<*>) trees otherTrees)
pure = Leaf
How can i make Monad type class instance for this tree?
I try
instance Monad (EvalATree b) where
return :: a -> EvalATree b a
(>>=) :: EvalATree b a -> (a -> EvalATree b c) -> EvalATree b c
(Leaf a) >>= f = f a
(Node g trees) >>= f = Node (g >>= f) (fmap (>>= f) trees)
return = pure
But i cant unwrap f to get type "c". Expected: type [b] -> c
EvalATree bhas noMonadinstance that’s compatible with thisApplicativeinstance, for the same reason asZipList: given two inputs with different lengths, combining them by zipping will truncate the longer one. So theMonadinstance isn’t associative—depending on how computations are grouped, you can get different results. A zippyMonadinstance is valid only if the inputs are always the same shape—such as a fixed-length vector/tuple, or an infinite stream.However, I think this tree type may not be quite what you want anyway. I assume you wanted
Node f tsto represent taking the results of the computationsts, and giving them as inputs to the functionf. But there’s no connection between the result typeaand the input typeb, without further assumptions aboutb. YourApplicativeinstance doesn’t offer a way to make anEvalATree b athat actually uses the[b].So it’s hard to say what you should do without more context, but here are some suggestions for things to try.
Just skip writing a
Monadinstance. You can still usedonotation withApplicativeDo.Change the
Applicativeinstance to use a Cartesian product, like lists.Make
ApplicativeandMonadinstances with some constraints, such asMonoid b.Get rid of the type parameter
b, merging it witha.Use
[a]orMonoid a => ainstead ofEvalATree b a.