自动将中缀运算符提升为单元中缀运算符

发布于 2024-12-09 14:43:10 字数 655 浏览 0 评论 0原文

Haskell 的优点之一是能够使用中缀表示法。

1 : 2 : 3 : []    :: Num a => [a]
2 + 4 * 3 + 5     :: Num a => a

但当操作员需要被抬起时,这种力量突然而悲伤地消失了。

liftM2 (*) (liftM2 (+) m2 m4) (liftM2 (+) m3 m5)
liftM2 (:) m1 (liftM2 (:) m2 (liftM2 (:) m3 mE))

可以定义类似的运算符来重新获得这种能力

(.*) = liftM2 (*)
(.+) = liftM2 (+)
(.:) = liftM2 (:)

m1, m2, m3, m4, m5 :: Monad m, Num a => m a
mE = return []     :: Monad m => m [a]
m1 .: m2 .: m3 .: mE    :: Monad m, Num a => m [a]
m2 .+ m4 .* m3 .+ m5    :: Monad m, Num a => m a

,但是需要重命名我想在单子上下文中使用的每个运算符是很乏味的。有更好的办法吗?也许是 Haskell 模板?

One of the nice things about Haskell is the ability to use infix notation.

1 : 2 : 3 : []    :: Num a => [a]
2 + 4 * 3 + 5     :: Num a => a

But this power is suddenly and sadly lost when the operator needs to be lifted.

liftM2 (*) (liftM2 (+) m2 m4) (liftM2 (+) m3 m5)
liftM2 (:) m1 (liftM2 (:) m2 (liftM2 (:) m3 mE))

It is possible to define similar operators in order to regain this power

(.*) = liftM2 (*)
(.+) = liftM2 (+)
(.:) = liftM2 (:)

m1, m2, m3, m4, m5 :: Monad m, Num a => m a
mE = return []     :: Monad m => m [a]
m1 .: m2 .: m3 .: mE    :: Monad m, Num a => m [a]
m2 .+ m4 .* m3 .+ m5    :: Monad m, Num a => m a

But it is tedious to need to rename every operator I want to use in a monadic context. Is there a better way? Template Haskell, perhaps?

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

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

发布评论

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

评论(3

痴梦一场 2024-12-16 14:43:10

您可以创建 Num: 的所有 monad 实例:

{-# LANGUAGE FlexibleInstances, FlexibleContexts, UndecidableInstances #-}

import Control.Monad

instance (Monad m, Num n, Show (m n), Eq (m n)) => Num (m n) where
  (+) = liftM2 (+)
  (*) = liftM2 (*)

然后您可以执行 fe:

*Main> [3,4] * [5,6] + [1,2]
[16,17,19,20,21,22,25,26]

但这仅适用于使用类型类定义的运算符。对于 : 这是不可能的。

You can make all monads instances of Num:

{-# LANGUAGE FlexibleInstances, FlexibleContexts, UndecidableInstances #-}

import Control.Monad

instance (Monad m, Num n, Show (m n), Eq (m n)) => Num (m n) where
  (+) = liftM2 (+)
  (*) = liftM2 (*)

Then you can do f.e.:

*Main> [3,4] * [5,6] + [1,2]
[16,17,19,20,21,22,25,26]

But this only works for operators that are defined with type classes. With : this isn't possible.

-小熊_ 2024-12-16 14:43:10

您可以定义一个新的中缀提升:

v <. f = liftM2 f v
f .> v = f v

使用示例:

[3] <.(+).> [4]

...但我不知道有什么真正的方法不是 100% 烦人。

You can define a new infix lift:

v <. f = liftM2 f v
f .> v = f v

Example use:

[3] <.(+).> [4]

...but I don't know of any real way that isn't 100% annoying.

时间海 2024-12-16 14:43:10

有使用 ap 的样式:

return (:) `ap` Just 1 `ap` Just []

或 applicative 样式:

(:) <
gt; Just 1 <*> Just []

There is the style using ap:

return (:) `ap` Just 1 `ap` Just []

or applicative style:

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