2015-03-17 2 views
2

Я играл с монадой Reader в Purescript, и я столкнулся с странным поведением. Я не знаю, так ли это из-за моего отсутствия понимания этой монады, или если мне не хватает чего-то другого.Reader Monad in Purescript

Это мой код:

type Level = Number 
type Doc = Reader Level String 

renderLine :: String -> Level -> String 
renderLine s 0 = s 
renderLine s l = "\t" ++ (renderLine s (l - 1)) 

line :: String -> Doc 
line s = do 
    level <- ask 
    return (renderLine s level) 

Это нормально и будет компилировать. Тем не менее, до этого я пытался что-то более простое в моей функции линии, как это:

line :: String -> Doc 
line s = do 
    level <- ask 
    return "Hello Reader monad" 

И это не компилируется, несмотря на то, что (уровень renderLine S) и «Hello Считыватель монада» имеет тот же тип. Он бросит мне эту ошибку: "Нет экземпляр найден Control.Monad.Reader.Class.MonadReader u14555 (Control.Monad.Reader.Trans.ReaderT Prim.Number Control.Monad.Identity.Identity)"

I «Конечно, я что-то упускаю, но я не знаю, что.

ответ

7

Более читаемый вариант этой ошибки будет:

No instance found for MonadReader ? (Reader Number)

Я думаю, что проблема здесь связана с отсутствием функциональных зависимостей в PureScript - в Haskell MonadReader класс определяется как MonadReader r m | m -> r так r определяется m, но мы не можем сделать это в PureScript.

Я подозреваю, что причина это работает в первом случае, а не последний тип level в настоящее время объединены с Level в вызове renderLine, что означает, поэтому r также должны быть Level.

Как вы ничего не делаете с level в последнем случае тип переменной остается не-унифицированы, а вот где ошибка происходит из, как там действительно нет экземпляра для MonadReader когда r неизвестно.

+0

Спасибо! Действительно хорошее объяснение :) –

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