haskell - 被 (->) 作为 monad 和 functor 的实例所吸引

标签 haskell

我对 (->) 很感兴趣当我查找有关 (->) 的信息时在 ghci 中。它说,

data (->) a b -- Defined in `GHC.Prim`

到目前为止一切都很好,但是当它说 -
instance Monad ((->) r) -- Defined in `GHC.Base`
instance Functor ((->) r) -- Defined in `GHC.Base`

这意味着什么?为什么 GHC 将其定义为 Monad 的实例,而 Functor 定义为 (->) ?

最佳答案

一开始可能有点困惑,但要记住的一个重要概念是 (->)不是单子(monad)或仿函数,而是 (->) r是。 MonadFunctor类型都有 * -> * ,所以他们只期望一个类型参数。

这意味着 fmap对于 (->) r好像

fmap g func = \x -> g (func x)

这也被称为
fmap g func = g . func

这只是正常的功能组合!当你fmap g超过 func ,您可以通过应用 g 来更改输出类型给它。在这种情况下,如果 func类型为 a -> b , g必须有类似 b -> c 的类型.
Monad实例更有趣。它允许您在应用程序发生“之前”使用函数应用程序的结果。帮助我理解的是看到一个例子
f :: Double -> (Double,Double)
f = do
    x1 <- (2*)
    x2 <- (2+)
    return (x1, x2)

> f 1.0
(2.0, 3.0)

这样做是将隐式参数应用于 f绑定(bind)到右侧的每个函数。所以如果你传入 1.0f ,它将绑定(bind)值 2 * 1.0x1并绑定(bind) 2 + 1.0x2 ,然后返回 (x1, x2) .它确实很容易将单个参数应用于许多子表达式。这个函数相当于
f' x = (2 * x, 2 + x)

为什么这很有用?一种常见的用法是 Reader monad,它只是 (->) r 的新类型包装器. Reader monad 可以很容易地在应用程序中应用静态全局配置。你可以编写如下代码
myApp :: Reader Config ()
myApp = do
    config <- ask
    -- Use config here
    return ()

然后你用 runReader myApp initialConfig 运行你的应用程序。 .您可以在 Reader Config 中轻松编写操作monad,组合它们,将它们链接在一起,它们都可以访问全局的只读配置。另外还有一个小伙伴ReaderT monad 转换器,它允许您将其构建到您的转换器堆栈中,让您拥有可以轻松访问静态配置的非常复杂的应用程序。

关于haskell - 被 (->) 作为 monad 和 functor 的实例所吸引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21026021/

相关文章:

function - 重复应用一个函数,直到结果稳定

java - 排序算法效率

haskell - 列表的唯一元素和相应的索引

haskell - 在 Yesod 中发送 301 重定向

haskell - 关联列表的镜头

c - Sqlite 外键

haskell - Haskell 发生了怎样的变化?

Haskell:如何播种(设置 Data.Random 使用的熵)?

Haskell - 如何打印函数中的某些值以进行调试?

haskell - 将类型族实例转换为 Int