题
我学习单元,并有几个问题。
这是我在哪里,现在。请纠正我,我错了。
的
>>=
符号是一个缀操作员。缀运营商职能,把两个参数(左手边右手边)和返回的价值。的
>>=
符号被称为结合运营商和有签名Monad m => m t -> (t -> m u) -> m u
.但是,该种类型似乎并不线在这里。我们得到一个值的类型m t
和第二个论点是一个功能,需要一个t
.(我看不出如何连接点。)这个必须意味着绑功能是某种程度上能够消除的
m
从m t
为了得到t
并通过它的功能。
这里是我的问题:
是的去除能力
m
从m t
东西是唯一可能的内部这样的结合运营商。这不会结合运营者具有某些特殊权限或什么的吗?什么是它必须做的状态的变化?我的理解(我认为)的目标的元是'包装'侧重效果使他们孤立于其余的程序。但是什么是角色的操作绑定在这个吗?
解决方案
是能够消除'M'从'M t'的东西是唯一可能的内部这样的结合运营商。这不会结合运营者具有某些特殊权限或什么的吗?
绑定不以任何方式的一种特殊情况,但通常会被定义相同的模块作为元数据的类型。因此,它可能知道关于(和使用)的详细信息,不会出口的模块。通常的情况是,该模块出口数据类型,而不是它的构造或其他细节有关类型内的结构。然后,用于代码使用该模块的内部运作的数据类型的无形代码不能直接修改的价值观的这种类型。
而不是功能,定义模块内,例如像某些操作绑定的 >>=
, 可以访问任何他们喜欢的模块,它们的定义。因此,这种功能可能是能够做到的事情"外部的"功能不能做。
一个特殊的情况下是的 IO
单的,因为这不是定义的一个模块,而是建立进入运行系统编译器。这里的编译器知道关于内部细节的执行情况和公开的功能喜欢 IO
's >>=
.实现这些职能确实是特别的特权,因为他们生活"之外的程序",但这是一个特殊的情况和这一事实不应当可观察到从内Haskell.
什么是它必须做的状态的变化?我的理解(我认为)的目标的元是'包装'侧重效果使他们孤立于其余的程序。但是什么是角色的操作绑定在这个吗?
它并不真正需要有与国家的改变,这只是一个问题,可以处理与moands.的 IO
单是用于具有IO执行在一定的顺序,但一般单元,都是种方法的功能结合在一起。
通常一个单(具体地说,它是结合的功能)的定义的方式的某些职能应由在一起更大的职能。这种方法相结合的职能是抽象的单.究竟如何,这种结合的工作,或者为什么你会想要结合职能,在这样一种方式是不重要的是,单只是指一种方法相结合的某些职能以某种方式。(也请参看 这种"异C#程序"的回答 我基本上重复了几次的例子。)
其他提示
是能够消除'M'从'M t'的东西是唯一可能的内部这样的结合运营商。
嗯,这当然是可能的内部操作绑定,作为其类型的规定:
(>>=) :: m a -> (a -> m b) -> m b
该"运行"功能单通常可以这样做,以及(返回一个纯粹的价值计算).
我们的目标的元是'包装'侧重效果使他们孤立于其余程序
嗯。不,异常让我们型观念的计算。侧面影响的计算只是一个这样的概念,如是国家,回溯,延续、并发性的交易,可选的结果,随机的结果,revertable国家、非决定论...所有这些 可以被描述为一个单
IO单是什么你是说,我假定。这是一个有点奇怪单--它的产生顺序的抽象变化的世界的状态,然后进行评估的运行时间。绑定只是让我们序的事情的正确顺序,在IO单--和编译器,随后将翻译成所有这些有序的世界中修改的行动为势在必行的代码变化的机器状态。
这是非常具体的IO单虽然不元。
以下是该定义的种类 Monad
.
class Monad m where
(>>=) :: forall a b. m a -> (a -> m b) -> m b
(>>) :: forall a b. m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
m >> k = m >>= \_ -> k
fail s = error s
每个类型的实例类型的流 Monad
定义自己的 >>=
功能。这里是一个例从型实例 Maybe
:
instance Monad Maybe where
(Just x) >>= k = k x
Nothing >>= _ = Nothing
(Just _) >> k = k
Nothing >> _ = Nothing
return = Just
fail _ = Nothing
正如我们所看到的,因为 Maybe
版本的 >>=
是专门定义的理解的 Maybe
类型实例,因为它限定在一个地方,有法律访问 data Maybe a
数据的构造 Nothing
和 Just a
, , Maybe
版本的 >>=
能够解开的 a
's Maybe a
并通过他们通过。
通过工作中的一个例子,我们可能采取:
x :: Maybe Integer
x = do a <- Just 5
b <- Just (a + 1)
return b
De-加糖、做记号变为:
x :: Maybe Integer
x = Just 5 >>= \a ->
Just (a + 1) >>= \b ->
Just b
其中评估为:
= (\a ->
Just (a + 1) >>= \b ->
Just b) 5
= Just (5 + 1) >>= \b ->
Just b
= (\b ->
Just b) (5 + 1)
= Just (5 + 1)
= Just 6
这类执行了,有趣的是足够的。这里是怎么样。
记住,一个单也是一个函数.下列功能的定义的所有函:
fmap :: (Functor f) => (a -> b) -> f a -> f b
现在的问题:做这些类型真的行吗?嗯,是的。给出一个功能 a
要 b
, 然后,如果我们有一个环境 f
在哪 a
是,我们有一个环境 f
在哪 b
是可用的。
通过类似于三段论:
(Functor Socrates) => (Man -> Mortal) -> Socrates Man -> Socrates Mortal
现在,你知道,一个单一的函子配备结合和返回:
return :: (Monad m) => a -> m a
(=<<) :: (Monad m) => (a -> m b) -> m a -> m b
你可能不知道,等效,这是一个函子设备齐全与返回,并加入:
join :: (Monad m) => m (m a) -> m a
看看我们是如何剥离掉 m
.有一个单 m
, 你不能总是得到从 m a
要 a
, 但是你总是可以得到从 m (m a)
要 m a
.
现在来看看第一个参数 (=<<)
.这是一个功能的类型 (a -> m b)
.发生什么事当您通过这一功能 fmap
?你得到 m a -> m (m b)
.因此,"mapping"超过一个 m a
用一个功能 a -> m b
给你 m (m b)
.请注意,这是完全一样的类型参数 join
.这不是一个巧合。一个合理的执行情况"捆绑"看起来是这样的:
(>>=) :: m a -> (a -> m b) -> m b
x >>= f = join (fmap f x)
事实上,结合和加入可以被定义在条款:
join = (>>= id)
我非常建议你读(http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html).它提供了一个完美的,普通意义上的原因,为什么单子存在。
我的理解(我认为)的目标的元是'包装'侧重效果使他们孤立于其余的程序。
它实际上是一个有点更加微妙。异使我们能够模型的排序在一个非常一般的方式。常常,当你跟一个领域的专家,你找到他们说什么"第一我们尝试X.然后我们尝试Y,如果不工作然后我们尝试Z"。当你来到实施类似的东西,在常规语言,你找到它不合适的,所以你必须要写大量的额外的代码,以涵盖无论该领域专家的意思是这个词"那么".
在Haskell,你可以实现这个作为单与"然后"翻译为结合运营商。例如,我曾经写了一个程序,一项已被分配从池根据某些规则。案例1你把它从游泳池X.如果这是空的,然后你搬到游泳池Y。案例2,你不得不把它直接从游泳池Y。所以在对十多个案件,包括一些你花了最近使用的从游泳池X或Y。我写了一个自定义的单专门为此工作,所以,我可以写:
case c of
1: do {try poolX; try poolY}
2: try poolY
3: try $ lru [poolX, poolY]
它的工作非常好。
这当然包括常规型号的顺序。IO单的模式,其他所有编程语言;它只是在Haskell其明确的选择,而不是部分的环境。ST单给你的记忆突变的IO,但没有实际输入和输出。另一方面国家单可以限制你的状态到一个单一的价值的一名类型。
一些真正的大脑弯曲,看到 这篇文章 关于落后状态单.国家传播方向相反的方向"执行".如果你认为这样一个国家执行单一指令后下,那么一个"放"将发送国价值的时间向后任何前"得到"。什么样的 实际上 发生的情况是,一个相互递归功能得到设立,只有终止,如果没有矛盾。我不知道在哪里使用这种单,但说明了这一点有关单元是模型的计算。
如果你是不是准备好了,然后只是觉得的结合作为一个可重载的分号。这让你很长的路要走。