Reputation: 9370
I have a recursive type: data E a=A a (E a) (E a) | None
My problem is the following :
If i want to implement the bind
operator how do i operate on both the Concrete type and the recursive one given the function to operate with?
instance Monad E where
return x= A x None None
(>>=) None _ = None
(>>=) (B t) f = f t
(>>=) (A x mx my) f = A {f x} (mx>>=f) (my>>=f) --here !!!
^
result is ma but slot requires concrete type
For me to apply >>=
on A a (E a) (E a)
for the a
it seems i need to unwrap it using a custom made function
.
How do i solve the {f x}
so that i unwrap the result of f x
to fit in the concrete slot of the E
I would need for a method that can take a function: a-> ma
and get it to (ma ->a)
unwrap::E a->a
unwrap None= what here ? ( i need a neutral element for any kind of a)
unwrap (A x _ _)=x
Upvotes: 1
Views: 193
Reputation: 60503
To overcome your specific challenge, you should try pattern matching on the result of f x
.
(>>=) (A x mx) f =
case f x of
A y my ->
B y ->
None ->
Now you have perhaps a larger problem than the one you came in with. There are now too many choices, as opposed to a poverty of them. In the A y my
case, you must combine y
, my
, and mx
into the final result in some way. Very likely most of the ways you think of will violate the laws.
In this case it is hard to know what to do. It is hard for me to implement a monad unless I am clear about the meaning of the data type. I can "visualize" list as a monad because join
(aka (>>= id)
) is just concatenation
join :: [[a]] -> [a]
join [ [ x, y ], [z], [], [w, q] ] = [x, y, z, w, q]
But for an arbitrary algebraic data type there is no clear path. Where did this data type come from? -- what do you want from its monad instance?
Upvotes: 3