Dan*_*ton 9 monads haskell infix-notation
Haskell的一个好处是能够使用中缀表示法.
1 : 2 : 3 : [] :: Num a => [a]
2 + 4 * 3 + 5 :: Num a => a
Run Code Online (Sandbox Code Playgroud)
但是当操作员需要被抬起时,这种力量突然而且可悲地丢失了.
liftM2 (*) (liftM2 (+) m2 m4) (liftM2 (+) m3 m5)
liftM2 (:) m1 (liftM2 (:) m2 (liftM2 (:) m3 mE))
Run Code Online (Sandbox Code Playgroud)
可以定义类似的运算符以重新获得此功率
(.*) = 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
Run Code Online (Sandbox Code Playgroud)
但是,需要重命名我想在monadic上下文中使用的每个运算符是很繁琐的.有没有更好的办法?模板Haskell,也许?
Sjo*_*her 10
您可以创建以下所有monad实例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 (*)
Run Code Online (Sandbox Code Playgroud)
然后你可以做fe:
*Main> [3,4] * [5,6] + [1,2]
[16,17,19,20,21,22,25,26]
Run Code Online (Sandbox Code Playgroud)
但这仅适用于使用类型类定义的运算符.随着:这是不可能的.
您可以定义新的中缀电梯:
v <. f = liftM2 f v
f .> v = f v
Run Code Online (Sandbox Code Playgroud)
使用示例:
[3] <.(+).> [4]
Run Code Online (Sandbox Code Playgroud)
...但我不知道任何真正的方式不是100%烦人的.