简体   繁体   English

将中缀运算符自动提升到monadic中缀运算符

[英]Automatic lifting of infix operators to monadic infix operators

One of the nice things about Haskell is the ability to use infix notation. Haskell的一个好处是能够使用中缀表示法。

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. 但是,需要重命名我想在monadic上下文中使用的每个运算符是很繁琐的。 Is there a better way? 有没有更好的办法? Template Haskell, perhaps? 模板Haskell,也许?

You can make all monads instances of Num : 您可以创建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 (*)

Then you can do fe: 然后你可以做fe:

*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. 随着:这是不可能的。

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. ...但我不知道任何真正的方式不是100%烦人的。

There is the style using ap : 有使用ap的风格:

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

or applicative style: 或适用风格:

(:) <$> Just 1 <*> Just []

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM