[英]Intrigued by (->) as instances of monad and functor
I am quite intrigued by (->)
when I looked up in information about (->)
in ghci. 当我在ghci中查找
(->)
信息时,我对(->)
非常感兴趣。 It says, 它说,
data (->) a b -- Defined in `GHC.Prim`
So far so good, but then it gets very interesting when it says - 到目前为止一切都那么好,但是当它说 - 时它变得非常有趣 -
instance Monad ((->) r) -- Defined in `GHC.Base`
instance Functor ((->) r) -- Defined in `GHC.Base`
What does this implicate? 这意味着什么? Why does GHC define it as an instance of a Monad, and Functor for
(->)
? 为什么GHC将它定义为Monad的实例,以及
(->)
Functor?
It can be a bit confusing at first, but one important concept to remember is that (->)
is not a monad or functor, but (->) r
is. 起初可能有点令人困惑,但要记住的一个重要概念是
(->)
不是monad或functor,但是(->) r
是。 Monad
and Functor
types all have the kind * -> *
, so they only expect one type parameter. Monad
和Functor
类型都有类型* -> *
,因此它们只需要一个类型参数。
What this means is that fmap
for (->) r
looks like 这意味着
(->) r
fmap
看起来像
fmap g func = \x -> g (func x)
Which is also known as 这也被称为
fmap g func = g . func
which is just normal function composition! 这只是正常的功能构成! When you
fmap g
over func
, you change the output type by applying g
to it. 当您通过
func
fmap g
时,可以通过对其应用g
来更改输出类型 。 In this case, if func
has the type a -> b
, g
must have a type like b -> c
. 在这种情况下,如果
func
的类型为a -> b
,则g
必须具有类似b -> c
的类型。
The Monad
instance is bit more interesting. Monad
实例更有趣。 It lets you use the result of a function application "before" that application has occurred. 它允许您在应用程序“之前”使用函数应用程序的结果。 What helped me understand was seeing an example like
帮助我理解的是看到一个例子
f :: Double -> (Double,Double)
f = do
x1 <- (2*)
x2 <- (2+)
return (x1, x2)
> f 1.0
(2.0, 3.0)
What this does is apply the implicit argument to f
to each of the functions on the right hand side of the binds. 这样做是将
f
的隐式参数应用于绑定右侧的每个函数。 So if you pass in 1.0
to f
, it will bind the value 2 * 1.0
to x1
and binds 2 + 1.0
to x2
, then returns (x1, x2)
. 因此,如果将
1.0
传递给f
,它会将值2 * 1.0
绑定到x1
并将2 + 1.0
绑定到x2
,然后返回(x1, x2)
。 It really makes it easy to apply a single argument to many subexpressions. 它确实可以很容易地将单个参数应用于许多子表达式。 This function is equivalent to
这个功能相当于
f' x = (2 * x, 2 + x)
Why is this useful? 为什么这有用? One common use is the
Reader
monad, which is simply a newtype wrapper around (->) r
. 一个常见的用途是
Reader
monad,它只是一个围绕(->) r
的newtype包装器。 The Reader
monad makes it easy to apply a static global config across your application. Reader
monad使您可以轻松地在应用程序中应用静态全局配置。 You could write code like 你可以写代码
myApp :: Reader Config ()
myApp = do
config <- ask
-- Use config here
return ()
And then you run your application with runReader myApp initialConfig
. 然后使用
runReader myApp initialConfig
运行应用程序。 You can easily write actions in the Reader Config
monad, compose them, chain them together, and all of them have access to the global, readonly config. 您可以轻松地在
Reader Config
monad中编写操作,组合它们,将它们链接在一起,并且所有这些操作都可以访问全局的readonly配置。 In addition, there's a companion ReaderT
monad transformer which allows you to build it into your transformer stack, letting you have very complex applications that have easy access to static configuration. 此外,还有一个配套的
ReaderT
monad变换器,允许您将其构建到变换器堆栈中,让您拥有非常复杂的应用程序,可以轻松访问静态配置。
I think it would be a bit less confusing if Haskell had just always allowed type operator sections: 我认为如果Haskell总是允许类型操作符部分,那会有点混乱:
data a->b
instance Monad (r -> )
looks much more natural. 看起来更自然。
For short explanation: I find it quite helpful to consider the special case Monad (Bool -> )
, which is basically a two-element container type. 简而言之:我发现考虑特殊情况
Monad (Bool -> )
非常有帮助,它基本上是一个双元素容器类型。 It has the two elements 它有两个要素
\case
False -> elem1
True -> elem2
So you can think about the functor instance much the same as for lists: map over "all contained elements". 因此,您可以考虑与列表相同的仿函数实例:映射“所有包含的元素”。
The applicative and monad instances are a bit different, it might help to make the "container transformation" explicit: applicative和monad实例有点不同,它可能有助于使“容器转换”显式:
data Pair a = Pair a a
instance Functor Pair where
fmap f (Pair a b) = Pair (f a) (f b)
instance Monad Pair where
return a = Pair a a
join (Pair (Pair a _) (Pair _ b))
= Pair a b
You can check yourself, for example at http://hackage.haskell.org/package/base-4.6.0.1/docs/src/GHC-Base.html 您可以查看自己,例如http://hackage.haskell.org/package/base-4.6.0.1/docs/src/GHC-Base.html
Copied from there: 从那里复制:
instance Functor ((->) r) where
fmap = (.)
instance Monad ((->) r) where
return = const
f >>= k = \ r -> k (f r) r
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.