Haskell 中的可变参数绑定

发布于 2024-12-10 03:48:43 字数 1063 浏览 0 评论 0原文

以下代码尝试编写一个如下所示的可变参数函数:

  • bind_variadic mx f = mx >>= f
  • bind_variadic mx my f = do { x <- mx; y <- 我的; 如果将“其余绑定”表示为变量 k,我可以编写它,但为了编写

类型类,我需要根据另一个函数编写一个函数。准确地说,我想用l0来表达l1,用l1来表达l2,等等。

import Prelude hiding ((>>=), (>>), Monad, return)

-- override the default monad so we don't get confusing
-- instances like "Monad (->)".
class Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  (>>) :: m a -> m b -> m b
  return :: a -> m a
  fail :: String -> m a

h :: Monad m => m a -> (t -> m b) -> (a -> t) -> m b
h mx k f = mx >>= \x -> k (f x)

l0 = h (return 3) id (\x -> return x)
l1 = h (return 3) (h (return 4) id) (\x y -> return x)
l2 = h (return 3) (h (return 4) (h (return 5) id)) (\x y z -> return x)

也许解决方案涉及另一个延续?

编辑

这里有一个需要额外加入的想法...

-- if not using Control.Monad, use this
join :: Monad 
              

The following code is an attempt to write a variadic function that acts like this:

  • bind_variadic mx f = mx >>= f
  • bind_variadic mx my f = do { x <- mx; y <- my; f x y }

I can write it if one expresses the "rest of binding" as a variable k, but in order to write a typeclass I need to write one function in terms of the other. To be precise, I want to express l1 in terms of l0, l2 in terms of l1, etc.

import Prelude hiding ((>>=), (>>), Monad, return)

-- override the default monad so we don't get confusing
-- instances like "Monad (->)".
class Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  (>>) :: m a -> m b -> m b
  return :: a -> m a
  fail :: String -> m a

h :: Monad m => m a -> (t -> m b) -> (a -> t) -> m b
h mx k f = mx >>= \x -> k (f x)

l0 = h (return 3) id (\x -> return x)
l1 = h (return 3) (h (return 4) id) (\x y -> return x)
l2 = h (return 3) (h (return 4) (h (return 5) id)) (\x y z -> return x)

Perhaps the solution involves another continuation?

edit

here's an idea that requires an additional join...

-- if not using Control.Monad, use this
join :: Monad ???? => ???? (???? α) -> ???? α
join mx = mx >>= id

-- idea: get side effects of evaluating first arguments first
h' mz k f = k f >>= \f' -> mz >>= (return . f')

l1' = h' (return 3) return
unary = join (l1' (\x -> return x))
l2' = h' (return 4) l1'
binary = join (l2' (\x y -> return x))
l3' = h' (return 5) l2'
ternary = join (l3' (\x y z -> return x))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

木有鱼丸 2024-12-17 03:48:43

如果你想表达这一点:

ap_variadic mx f = mx >>= f
ap_variadic mx my f = do { x <- mx; y <- my; f x y }

我会使用 Control.Applicative 代替。然后:

join (f <
gt; mx)
join (f <
gt; mx <*> my)
join (f <
gt; mx <*> my <*> mz)

我认为这比任何多元解决方案都更好(更简单,更易于维护)。

If you want to express this:

ap_variadic mx f = mx >>= f
ap_variadic mx my f = do { x <- mx; y <- my; f x y }

I would use Control.Applicative instead. Then:

join (f <
gt; mx)
join (f <
gt; mx <*> my)
join (f <
gt; mx <*> my <*> mz)

I think this is better (simpler, more maintainable) than any polyvariadic solution would be.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文