Почему это не случай ограничения монады? - PullRequest
0 голосов
/ 05 июля 2018

В следующем фрагменте кода я изначально считал, что имеет ограниченную ошибку монады (я забыл добавить Monad m => в определении instance Monad (Transform m a)). Прочитав довольно много об ограниченных монадах, я удивляюсь, почему все в порядке:

{-# LANGUAGE GADTs #-}

data Next a where
    Todo :: a -> Next a
    Done :: Next a

instance Functor Next where
    fmap f Done = Done
    fmap f (Todo a) = Todo (f a)

data Transform m a b = Monad m => Transform ( m(Next a) -> m(Next b) )

instance Functor (Transform m a) where
    fmap f (Transform ta) = Transform tb where
        tb ma = ta ma >>= return . (fmap f)

instance Applicative (Transform m a) where
    pure = return
    mf <*> ma = do
        f <- mf
        a <- ma
        return (f a)

instance Monad m => Monad (Transform m a) where
    return b = Transform (t b) where                
        t b _ = return $ Todo b
    (Transform t) >>= f = Transform (\ma -> do     
        a <- ma
        case a of
            Done -> return Done
            --Todo a' -> ...
        )

Пример довольно надуманный, я убрал все ненужные биты. (Актуальная проблема связана с этим .) Важнейшей частью является ограничение Monad m в Transform.

Я не совсем понимаю, чем это отличается от часто цитируемого канонического примера Set -as-a-monad, который действительно имеет ограниченное ограничение монады.

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Я не совсем понимаю, чем это отличается от часто цитируемого канонического примера "Set-as-a-monad", который демонстрирует ограниченное ограничение монады.

Это отличается, потому что ограничение не относится к последнему параметру типа, который варьируется в Monad. В случае Set это.

0 голосов
/ 05 июля 2018

Transform - не ограниченная монада.

Посмотрите на Set. Set является монадическим в одном аргументе, за исключением того, что аргумент должен быть Ord. То есть Set - это монада в подкатегории Hask, где все объекты находятся в Ord.

Но Transform это не монада во-первых. Transform :: (* -> *) -> * -> * -> *, но Monad относится к вещам типа * -> * (если вы собираетесь стать теоретиком полной категории, монады в целом являются эндофункторами и примерно должны иметь вид k -> k для некоторых k, но Transform не очень подходит для этого более широкого шаблона). Монада - это Transform m a, когда m - это монада. Transform m a является монадой на всем Hask, если m также является монадой. Вы видите разницу? Transform m a данный Monad m действует на все типы, которые есть. Но я ничего не могу вставить в пробел, чтобы "Set, учитывая, что ___ работает с каждым существующим типом", потому что ограничение распространяется на параметр, в котором Set является монадическим, в то время как Transform m a не имеет ограничение на тип, в котором оно монадическое, но на один из типов, который его составляет.

...