9

Haskell の優れた点の 1 つは、中置記法を使用できることです。

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 でしょうか。

4

3 に答える 3

10

のすべてのモナドのインスタンスを作成できます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 (*)

次に、feを実行できます:

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

ただし、これは型クラスで定義された演算子に対してのみ機能します。これ:では無理です。

于 2011-10-12T15:53:00.970 に答える
9

新しい中置リフトを定義できます。

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

使用例:

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

...しかし、100% 迷惑ではない本当の方法を私は知りません。

于 2011-10-12T16:15:11.353 に答える
2

を使用したスタイルがありますap

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

または適用可能なスタイル:

(:) <$> Just 1 <*> Just []
于 2011-10-12T16:56:40.897 に答える