Haskell麻烦为monad实例编写绑定函数(函数转换?)

时间:2014-12-21 17:39:40

标签: haskell bind monads

我需要编写以下函数:

bind :: ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)

Action是我定义的类型构造函数。麻烦的是当我尝试以下列方式实现它时:

bind f g = 

我不知道如何将类型“a”的值传递给函数g。我无法获得价值。

事实上,这看起来像某种功能转换为另一种功能,但我也不知道如何实现这一功能。

我该怎样做才能使这种转变成为可能?

2 个答案:

答案 0 :(得分:5)

这是Cont monad绑定。没有newtype包装器,它看起来像这样:

bind :: ((a -> r) -> r) -> (a -> ((b -> r) -> r)) -> ((b -> r) -> r)

首先,删除多余的括号:

bind :: ((a -> r) -> r) -> (a -> (b -> r) -> r) -> (b -> r) -> r

其次,让b -> r = br

bind :: ((a -> r) -> r) -> (a -> br -> r) -> br -> r

现在你有了

bind s f k = ?

其中s :: (a -> r) -> rf :: a -> br -> rk :: br

flip f k     :: a -> r
s (flip f k) :: r

所以

bind :: ((a -> r) -> r) -> (a -> ((b -> r) -> r)) -> ((b -> r) -> r)
bind s f k = s (flip f k)

或者只是

bind s f = s . flip f

或点免费

bind = (. flip) . (.)

答案 1 :(得分:3)

你的monad被称为continuation monad Cont r a = ((a->r)->r)(减去一个newtype包装器),在你的情况下r = Action。但是,让我们冒险一点,而不考虑如何定义monad ......

让我们大胆地开始:

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)
bind f g = (??? :: (b -> Action) -> Action)

所以,让我们开始填充???。我们需要生成一个函数,所以让我们利用lambda:

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)
bind f g = \k :: (b -> Action) -> (??? :: Action)

一旦克服了这一点,我们现在需要制作一个Action。我们手中有几个函数返回:f,g,k,每个函数都需要不同的args。这是一个反复试验的问题。我们猜猜...... f

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)
bind f g = \k :: (b -> Action) -> f (??? :: a -> Action)

我们再次需要一个功能:撒上更多的lambda,更多的lambdas!

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)
bind f g = \k :: (b -> Action) -> f (\x :: a -> (??? :: Action))

呻吟......,我们需要再次制作一个Action。我们做的事情毫无意义吗?我们在圈子里循环吗? ,我们现在有x :: a的范围,所以我们现在掌权了。我们现在使用g

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)
bind f g = \k :: (b -> Action) -> f (\x :: a -> g (???1 : a) (???2 :: b -> Action))

嗯,g的第一个参数现在很容易找到。

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)
bind f g = \k :: (b -> Action) -> f (\x :: a -> g x (???2 :: b -> Action))

更多的lambdas,更多的lambdas!

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)
bind f g = \k :: (b -> Action) -> f (\x :: a -> g x (\y :: b -> (??? :: Action)))

哎呀!不是另一个Action来制作!但一切都没有失去,我们掌权:我们现在有x::ay::b来电!我们也从未使用k ...嗯......

待办事项:

  1. 击败最后一个???
  2. 为monad提供return / unit函数。
  3. 证明monad法律。
  4. 利润!