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

Jer*_*uan 11 monads haskell

嗨,我正在尝试实现穷人的并发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)
Run Code Online (Sandbox Code Playgroud)

这是我的分析: x有类型b,y有类型a,f有类型(a -> ((b ->Action) -> Action)).为了弄清楚"Something return a Action",我首先计算(f y),返回一种类型((b ->Action) -> Action).然后,如何使用它x来生成一个Action?

Ste*_*ans 21

您正在寻找的定义类似于

Concurrent h >>= k  =  Concurrent (\f -> h (\x -> runConcurrent (k x) f))
Run Code Online (Sandbox Code Playgroud)

我们是怎么到达那里的?与往常一样,我们让类型完成工作.:)

我们先介绍一个辅助函数:

runConcurrent                 :: Concurrent b -> (b -> Action) -> Action
runConcurrent (Concurrent h)  =  h
Run Code Online (Sandbox Code Playgroud)

如果你从定义的左侧开始

Concurrent h >>= k  =  ...
Run Code Online (Sandbox Code Playgroud)

h :: (a -> Action) -> Actionk :: a -> Concurrent b,然后你的目标是...用类型的表达式替换Concurrent b,不是吗?

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

这给了:

Concurrent h >>= k = Concurrent ...
Run Code Online (Sandbox Code Playgroud)

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

Concurrent h >>= k  =  Concurrent (\f -> ...)
Run Code Online (Sandbox Code Playgroud)

这使我们f :: b -> Action有义务...用表达式替换Action.Action直接使用其中一个-constructors当然会作弊;).为了保证通用性(>>=)(更准确地说,确保我们最终遵守monad法则),我们将其Action视为抽象数据类型.然后,生成Action-value 的唯一方法是应用函数h:

Concurrent h >>= k  =  Concurrent (\f -> h ...)
Run Code Online (Sandbox Code Playgroud)

因此,接下来我们需要提供h类型的参数a -> Action.这又是一个函数类型,所以我们抛出另一个lambda:

Concurrent h >>= k  =  Concurrent (\f -> h (\x -> ...))
Run Code Online (Sandbox Code Playgroud)

因此,我们已经x :: a并且需要构建一个类型的主体Action.我们可以用类型的值做什么a?我们可以将它提供给该功能k.这给了我们一个类型的值Concurrent b,然后我们可以传递给我们的辅助函数runConcurrent:

Concurrent h >>= k  =  Concurrent (\f -> h (\x -> runConcurrent (k x) ...))
Run Code Online (Sandbox Code Playgroud)

这给了我们一个类型的函数,(b -> Action) -> Action并提供f作为参数的技巧:

Concurrent h >>= k  =  Concurrent (\f -> h (\x -> runConcurrent (k x) f))
Run Code Online (Sandbox Code Playgroud)