我需要编写以下函数:
bind :: ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action)
Action是我定义的类型构造函数。麻烦的是当我尝试以下列方式实现它时:
bind f g =
我不知道如何将类型“a”的值传递给函数g。我无法获得价值。
事实上,这看起来像某种功能转换为另一种功能,但我也不知道如何实现这一功能。
我该怎样做才能使这种转变成为可能?
答案 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) -> r
,f :: a -> br -> r
和k :: 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::a
和y::b
来电!我们也从未使用k
...嗯......
待办事项:
???
。return
/ unit函数。