Реализация монады по рекурсивному типу

У меня рекурсивный тип:
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]

Но для произвольного алгебраического типа данных нет четкого пути. Откуда появился этот тип данных? - что вы хотите от своего монадного экземпляра?


Есть идеи?

10000