Haskell 如何使用带有(Int->Int)的读卡器Monad?

Haskell 如何使用带有(Int->Int)的读卡器Monad?,haskell,monads,reader-monad,Haskell,Monads,Reader Monad,我想学习,如何使用阅读器Monad。不幸的是,只有少量的示例代码可用 我想创建一个读卡器,其中环境和检索值为Int。我定义了如下类型: type IntRead = Reader Int Int 我尝试的代码是: addStuff :: Reader Int Int addStuff = do a <- (*2) b <- (+10) return (a+b) 我得到一个错误,因为应该是ReaderT。如何使用Reader Monad创建像ad

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

我想创建一个读卡器,其中环境和检索值为Int。我定义了如下类型:

type IntRead = Reader Int Int
我尝试的代码是:

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

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

您可以将函数转换为读取器,然后使用以下两种同构进行转换:

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

或者更好

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实际使用一元读取器操作。

您可以将函数转换为读取器,然后使用以下两种同构进行转换:

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

或者更好

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来实际使用一元读取器操作。

您必须将函数映射到ask:a Thank you,但是如何在环境中调用addStuff呢?有了这段代码,我发现了一个错误:addStuff 10它取决于您的库。您需要一个与读取器AB->a->b同构的函数。它通常被称为runReader。您必须将函数映射到ask:a Thank You,但是如何在环境中调用addStuff呢?有了这段代码,我发现了一个错误:addStuff 10它取决于您的库。您需要一个与读取器AB->a->b同构的函数。它通常被称为runReader。它可能更好吗现在不要太担心聪明的代码或快捷方式。如果你正在学习,更重要的是如果你了解基础知识,例如它是如何工作的。如果有一段时间你会经常使用这两个同构,即使它对于实际的生产代码来说不是一个好的样式,也没关系。addStuff=liftA2+*2+10@amalloy但是这并没有使用读卡器单子,而是使用另一个读卡器单子->r:-P发现Haskell中有两个同构的读卡器单子会让人很困惑:好吧,如果您更喜欢使用asks包装器,您仍然可以执行相同的操作:liftA2+asks*2 asks+10是否可能更好现在不要太担心聪明的代码或快捷方式。如果你正在学习,更重要的是如果你了解基础知识,例如它是如何工作的。如果有一段时间你会经常使用这两个同构,即使它对于实际的生产代码来说不是一个好的样式,也没关系。addStuff=liftA2+*2+10@amalloy但是这并没有使用读卡器单子,而是使用另一个读卡器单子->r:-P发现Haskell中有两个同构的读卡器单子会让人很困惑:好吧,如果您更喜欢使用asks包装器,您仍然可以执行相同的操作:liftA2+asks*2 asks+10