Читательская монада в Purescript

Я играл с монадой Reader в 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 level) и "Hello Reader monad" имеют один и тот же тип. Это выдаст мне эту ошибку: «Не найден экземпляр для Control.Monad.Reader.Class.MonadReader u14555 (Control.Monad.Reader.Trans.ReaderT Prim.Number Control.Monad.Identity.Identity)»

Я уверен, что что-то упускаю, но не знаю что.


person ThomasC__    schedule 17.03.2015    source источник


Ответы (1)


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

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 неизвестен.

person gb.    schedule 17.03.2015