Реализация монады по рекурсивному типу - PullRequest
1 голос
/ 13 мая 2019

У меня рекурсивный тип:
data E a=A a (E a) (E a) | None
Моя проблема заключается в следующем:
Если я хочу реализовать оператор bind, как мне работать как с конкретным, так и с рекурсивным типомучитывая функцию для работы с?

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.

Как мне решить {f x}, чтобы развернуть результат f x, чтобы поместить его в конкретный слот 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 Ответ

3 голосов
/ 13 мая 2019

Чтобы преодолеть вашу конкретную проблему, вы должны попробовать сопоставление с шаблоном по результату f x.

(>>=) (A x mx) f = 
    case f x of
        A y my -> 
        B y -> 
        None -> 

Теперь у вас, возможно, проблема большего размера, чем та, с которой вы пришли.Сейчас слишком много вариантов, в отличие от их бедности.В случае A y my вы должны каким-то образом объединить y, my и mx в конечный результат.Весьма вероятно, что большинство ваших способов нарушит законы.

В этом случае сложно понять, что делать.Мне трудно реализовать монаду, если я не понимаю, что означает типа данных.Я могу «визуализировать» список как монаду, потому что join (он же (>>= id)) - это просто конкатенация

join :: [[a]] -> [a]
join [ [ x, y ], [z], [], [w, q] ] = [x, y, z, w, q]

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

...