>> =穷人的并发Monad的实现

时间:2014-11-28 14:36:23

标签: 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) >>= f = Concurrent (\x -> ma(\y -> "Something return a Action")) 
    return x = Concurrent (\c -> c x)

这是我的分析: x的类型为by的类型为af的类型为(a -> ((b ->Action) -> Action))。为了找出“Something return a Action”,我首先计算(f y),它返回((b ->Action) -> Action)的类型。然后,如何将其与x一起使用以生成Action?

1 个答案:

答案 0 :(得分:21)

您正在寻找的定义类似于

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) -> Actionk :: a -> Concurrent b,那么您的目标是将...替换为Concurrent b类型的表达式,不是吗?

我们如何构建Concurrent b类型的值?一种方法是应用我们的函数k,但这不会起作用,因为我们没有合适的a类值作为参数。所以,我们唯一能做的就是应用Concurrent类型的数据构造函数((b -> Action) -> Action) -> Concurrent b

这给出了:

Concurrent h >>= k = Concurrent ...

现在我们必须找到(b -> Action) -> Action类型的表达式作为Concurrent的参数。我们知道函数类型的表达式总是可以通过lambda-abstraction构建:

Concurrent h >>= k  =  Concurrent (\f -> ...)

这为我们提供了f :: b -> Action,并且有义务使用...类型的表达式替换Action。直接使用其中一个Action - 构造函数当然会作弊;)。为了保证(>>=)的通用性(更确切地说,为了确保我们最终遵守monad法则),我们将Action视为抽象数据类型。然后,生成Action - 值的唯一方法是应用函数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))