Тип ошибки при попытке реализовать функцию (>> =), чтобы создать пользовательский монадский трансформатор

StackOverflow https://stackoverflow.com/questions/2661895

Вопрос

Я пытаюсь создать монадский трансформатор для будущего проекта, но, к сожалению, моя реализация функции Monad TypeClasse (>> =) не работает.

Прежде всего, вот основной монадской реализации:

newtype Runtime a = R { 
  unR :: State EInfo a
} deriving (Monad)

Здесь реализация Monad TypeClasse осуществляется автоматически GHC (используя GeneralizedNewtypeDeriving Языковая прагма). Монадский трансформатор определяется как:

newtype RuntimeT m a = RuntimeT {
  runRuntimeT :: m (Runtime a)
} 

Проблема приходит от того, как я указываю функцию (>> =) функции монады TypeClasse:

instance (Monad m) => Monad (RuntimeT m) where
    return a = RuntimeT $ (return . return) a
    x >>= f =  runRuntimeT x >>= id >>= f

Как я вижу это, первый >>= бежит в основе базового m монад Таким образом, runRuntimeT x >>= Возвращает значение типа Runtime a (правильно ?). Затем следующий код, id >>=, должен вернуть значение типа a. Отказ Это значение передается на функцию f тип типа f :: (Monad m) => a -> RuntimeT m b.

И вот поставляется проблема типа: f Тип функции не соответствует типу, требуемую функцией (>> =). JOW Могу ли я сделать это согласованность? Я вижу, почему это не работает, но мне не удалось превратить его во что-то функциональное.

Редактировать: сообщение об ошибке:

Core.hs:34:4:
    Occurs check: cannot construct the infinite type: m = RuntimeT m
    When generalising the type(s) for `>>='
    In the instance declaration for `Monad (RuntimeT m)'
Failed, modules loaded: none.

Спасибо, что вы помогите, и не стесняйтесь исправлять любые недостатки в моем сообщении,
Чарли П.

Это было полезно?

Решение

Следовать от того, что Рейд Бартон сказал о StateT - вот как вы бы определили RuntimeT с использованием StateT. Отказ То Runtime Затем Монад может быть тривециально определен с использованием личности монада.

newtype RuntimeT m a = R { 
  unR :: StateT EInfo m a
}

type Runtime = RuntimeT Identity

instance Monad m => Monad (RuntimeT m) where
    return = R . return

    (R m) >>= f = R (m >>= unR . f)

Другие советы

Обычно StateT s m Монад отправляет a к s -> m (a, s) Но вы работаете с m (s -> (a, s)) вместо. Я не думаю, что последние формируют монад для общего s. Отказ Вы уверены, что вы не просто хотите использовать StateT?


Вот почему я не думаю am (s -> (a, s)) это монад: писать >>= Мне нужна функция, которая принимает аргументы типов

m (s -> (a, s))
a -> m (s -> (b, s))

и возвращает значение типа

m (s -> (b, s))

«Эффекты» (т.е. fmap (const ())) результата должны быть те из первого аргумента, поскольку у нас нет возможности получить a перейти ко второму аргументу. С m появляется только снаружи типа результата, мы тогда не можем использовать второй аргумент для чего-либо вообще - не будет способа избавиться от m это вводит.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top