У меня рекурсивный тип:
data E a=A a (E a) (E a) | None
Моя проблема заключается в следующем:
Если я хочу реализовать оператор bind
как мне работать как с типом Concrete, так и с рекурсивным типом, учитывая функцию, с которой нужно работать?
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
Для меня, чтобы применить >>=
на A a (E a) (E a)
для a
мне кажется, что мне нужно развернуть его с помощью пользовательской function
.
Как мне решить {fx}
так, чтобы я развернул результат fx
чтобы поместиться в конкретный слот E
Мне нужен метод, который может взять функцию: a-> ma
и получить ее в (ma ->a)
unwrap::E a->a
unwrap None= what here ? ( i need a neutral element for any kind of a)
unwrap (A x _ _)=x
Всего 1 ответ
Чтобы преодолеть вашу конкретную проблему, вы должны попробовать сопоставление с образцом по результату fx
.
(>>=) (A x mx) f =
case f x of
A y my ->
B y ->
None ->
Теперь у вас, возможно, более серьезная проблема, чем та, с которой вы пришли. Сейчас слишком много вариантов, в отличие от их бедности. В случае A y my
вы должны каким-то образом объединить y
, my
и mx
в конечный результат. Скорее всего, большинство способов, которыми вы думаете, будут нарушать законы.
В этом случае трудно понять, что делать. Мне сложно реализовать монаду, если я не знаю, что означает тип данных. Я могу «визуализировать» список как монаду, потому что join
(aka (>>= id)
) - это просто конкатенация
join :: [[a]] -> [a]
join [ [ x, y ], [z], [], [w, q] ] = [x, y, z, w, q]
Но для произвольного алгебраического типа данных нет четкого пути. Откуда появился этот тип данных? - что вы хотите от своего монадного экземпляра?