2014-12-10 3 views
1

Я пытаюсь сделать монаду читателя, но он не работает (нагрузка), что я делаю неправильно? БлагодаряЧитатель monad core operator не работает

newtype Reader r a = Reader { runReader :: r -> a } 

instance Monad (Reader r) where 
    return a = Reader $ \r -> a 

    Reader m >>= f = Reader $ \r -> 
     let a = m r 
     in runReader (f a) 

Я получаю эту ошибку:

Couldn't match type ‘b’ with ‘r -> b’ 
    ‘b’ is a rigid type variable bound by 
     the type signature for 
     (>>=) :: Reader r a -> (a -> Reader r b) -> Reader r b 
     at Reader.hs:24:14 
Expected type: Reader r b 
    Actual type: Reader r (r -> b) 
Relevant bindings include 
    f :: a -> Reader r b (bound at Reader.hs:24:18) 
    m :: r -> a (bound at Reader.hs:24:12) 
    (>>=) :: Reader r a -> (a -> Reader r b) -> Reader r b 
    (bound at Reader.hs:24:5) 
In the expression: Reader $ \ r -> let a = ... in runReader (f a) 
In an equation for ‘>>=’: 
    (Reader m) >>= f = Reader $ \ r -> let ... in runReader (f a) 
In the instance declaration for ‘Monad (Reader r)’ 

Failed, модули загружены: нет.

+0

См. Позже редактирование – yonutix

+0

Я думаю, вам могут понадобиться скобки '(Reader m)' при выполнении сопоставления с образцом – Mokosha

+0

@genisage Это точно ответ, и вы должны опубликовать его как таковой. – bheklilr

ответ

2

Правильная реализация:

newtype Reader r a = Reader { runReader :: r -> a } 

instance Monad (Reader r) where 
    return a = Reader $ \_ -> a 
    Reader m >>= f = Reader $ \r -> runReader (f $ m r) r 

Дополнительная путаница, что вы пропустили это в безвыходном окончательный r. Поскольку этого параметра нет, он утверждает, что вы принимаете r -> a за a, когда вы строите Reader (другими словами, вы передали его r -> r -> a, когда ему нужно всего лишь r -> a).

Чтобы понять, что происходит, это может помочь изучить тип runReader:

ghci> :t runReader 
runReader :: Reader r a -> r -> a 

Эта функция принимает в качестве первого аргумента читателя, в качестве второго аргумента r, и дает вам СПИНКИ a , Таким образом, мы можем видеть, что Подвыражение

\r -> runReader (f $ m r) r 

имеет тип r -> a и является хорошим кандидатом в руки прочь к Reader конструктора. Если вы опустите, что последний r вы только применять runReader к одному аргументу, и вы получите выделанной r -> a функцию как результат, так что:

\r -> runReader (f $ m r) 

имеет тип r -> r2 -> a и когда вы кормите его к считывателю вас» Получите Reader r (r2 -> a), который не имеет подходящего типа для >>=.

Смежные вопросы