2

我想学习如何使用 Reader Monad。不幸的是,只有少量示例代码可用

我想创建一个阅读器,其中环境和检索的值是Int. 我定义了这样的类型:

type IntRead = Reader Int Int

我试过的代码是这样的:

addStuff :: Reader Int Int
addStuff = do  
    a <- (*2)  
    b <- (+10)
    return (a+b)  

我得到一个错误,因为ReaderT是预期的。如何创建类似addStuff使用 Reader Monad 的函数?我应该在哪里为这个函数提供环境?

4

1 回答 1

7

您可以使用以下两种同构将函数转换为读取器并返回:

reader :: (r -> a) -> Reader r a
runReader :: Reader r a -> r -> a

例如

addStuff :: Reader Int Int
addStuff = do  
    a <- reader (*2)  
    b <- reader (+10)
    return (a+b)

然后您可以使用runReader addStuff 5.

这对于学习目的来说是可以的。对于更严肃的代码,您不应过多使用同构,而应依赖askor asks。例如

addStuff :: Reader Int Int
addStuff = do  
    x <- ask   -- fetch the implicit Int value
    let a = (*2) x
        b = (+10) x
    return (a+b)

或更好

addStuff :: Reader Int Int
addStuff = do  
    a <- asks (*2) -- fetch the implicit Int value, and apply the function
    b <- asks (+10)
    return (a+b)

或者,更好的是,使用应用风格:

addStuff :: Reader Int Int
addStuff = (+) <$> asks (*2) <*> asks (+10)

读者抽象的重点不是考虑底层功能。您可以假装可以访问只读变量,该变量可通过ask原语访问。

通常,仅在您runReader实际使用单子阅读器操作的最后一步。

于 2017-05-23T18:56:25.057 回答