Haskell &燃气轮机>;=穷人实施';s并发单子
嗨,我正在尝试实现穷人的并发Monad。 这是我的密码:Haskell &燃气轮机>;=穷人实施';s并发单子,haskell,monads,Haskell,Monads,嗨,我正在尝试实现穷人的并发Monad。 这是我的密码: import Control.Monad data Concurrent a = Concurrent ((a -> Action) -> Action) data Action = Atom (IO Action) | Fork Action Action | Stop instance Monad Concurrent where (Concurrent ma) >>=
import Control.Monad
data Concurrent a = Concurrent ((a -> Action) -> Action)
data Action
= Atom (IO Action)
| Fork Action Action
| Stop
instance Monad Concurrent where
(Concurrent ma) >>= f = Concurrent (\x -> ma(\y -> "Something return a Action"))
return x = Concurrent (\c -> c x)
以下是我的分析:
x
的类型为b
,y
的类型为a
,f
的类型为(a->((b->Action)->Action))
。为了计算“某物返回动作”,我首先计算(fy)
,它返回一种类型的((b->Action)->Action)
。那么,如何将它与x
一起使用来生成动作呢?您要查找的定义如下
Concurrent h >>= k = Concurrent (\f -> h (\x -> runConcurrent (k x) f))
我们是怎么到那里的?和往常一样,我们让类型完成工作。:)
让我们首先介绍一个辅助函数:
runConcurrent :: Concurrent b -> (b -> Action) -> Action
runConcurrent (Concurrent h) = h
如果你从定义的左边开始
Concurrent h >>= k = ...
使用h::(a->Action)->Action
和k::a->Concurrent b
,您的目标是用Concurrent b
类型的表达式替换…
,不是吗
我们如何构造类型为并发b
的值?一种方法是应用函数k
,但这不起作用,因为我们没有合适的a
类型的值作为参数。因此,我们能做的几乎是应用数据构造函数Concurrent
,它的类型是((b->Action)->Action)->Concurrent b
这就产生了:
Concurrent h >>= k = Concurrent ...
现在我们必须找到一个类型为(b->Action)->Action
的表达式,作为Concurrent
的参数提供。我们知道,函数类型的表达式始终可以通过lambda抽象来构造:
Concurrent h >>= k = Concurrent (\f -> ...)
这给了我们f::b->Action
以及用Action
类型的表达式替换..
的义务。直接使用操作之一-构造函数当然是作弊;)。为了保证(>>=)
(更准确地说,为了确保我们最终遵守monad定律),我们将操作
视为一种抽象数据类型。然后,生成操作
-值的唯一方法是应用函数h
:
Concurrent h >>= k = Concurrent (\f -> h ...)
因此,接下来我们需要为h
提供类型为a->Action
的参数。这又是一种函数类型,因此我们加入另一个lambda:
Concurrent h >>= k = Concurrent (\f -> h (\x -> ...))
因此,我们有x::a
,需要构造类型为Action
的主体。对于a
类型的值,我们可以做什么?我们可以将其提供给函数k
。这为我们提供了一个类型为Concurrent b
的值,然后我们可以将其传递给助手函数runConcurrent
:
Concurrent h >>= k = Concurrent (\f -> h (\x -> runConcurrent (k x) ...))
这为我们提供了一个类型为(b->Action)->Action
的函数,并作为参数提供f
,这样做的技巧如下:
Concurrent h >>= k = Concurrent (\f -> h (\x -> runConcurrent (k x) f))
你的分析是错误的x
的类型为b->Action
,而不是b
。您可能需要签出。它允许您录制单子,可以任意重放。我将它用于轻量级线程。数据构造函数并发
的小错误类型是((b->Action)->Action)->并发b
而不是((b->Action)->b)->并发b
。我说得对吗?@fdelsert你完全正确。谢谢你发现了。在回答中更正了它。