6

haskellで少し遊んだ後、私はこの関数に出くわしました:

Prelude Data.Maclaurin> :t ((+) . ($) . (+))
((+) . ($) . (+)) :: (Num a) => a -> (a -> a) -> a -> a

(Data.Maclaurinはパッケージvector-spaceによってエクスポートされます。)したがって、Num、関数、別のNumを取り、最終的にNumを返します。次の機能を実現する魔法は何ですか?

Prelude Data.Maclaurin> ((+) . ($) . (+)) 1 2 3
6

2は明らかに関数ではありません(a-> a)または私は何かを逃しましたか?

4

2 に答える 2

16

Data.NumInstances同じパッケージのモジュールは、数値を返す関数のインスタンスを定義します。Num

instance Num b => Num (a->b) where
  (+)         = liftA2 (+)
  (*)         = liftA2 (*)
  fromInteger = pure . fromInteger
  ...

Haskellでは、のような整数リテラル2は一般的であるため、次の任意のインスタンスの数値を表すことができますNum

Prelude> :t 2
2 :: (Num t) => t

それを特定のコンテキストで必要なタイプの実際の数に変換するために、クラスfromIntegerからが呼び出されます。Num

上記のヘルパーモジュールはNumfor関数のインスタンスを定義しているため、ここで指定されたメソッドを使用2して関数に変換できるようになりました。fromIntegerしたがって、ghciはfromInteger 2、質問の構成の2番目のパラメーターとして必要な関数を取得するために呼び出します。次に、式全体がたまたまに評価され6ます。

于 2010-03-22T23:56:31.337 に答える
1

混乱するのには十分な理由があります。Data.NumInstancesGHC(によってロードされる)のモジュールを使用すると、定数関数Data.Maclaurinに強制することができます。Num

Prelude Data.NumInstances> :t (2 :: (Num a) => a -> a)
(2 :: (Num a) => a -> a) :: (Num a) => a -> a
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 0          
2
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 1000
2

式の評価は、本質的に、

((+) . ($) . (+)) 1 2 3 = ((+) . ($) . (1+)) 2 3
                        = ((+) (1+)) 2 3
                        -- (+) is defined for functions that return a Num
                        = ((+) (1+) (\_ -> 2)) 3  
                        = ((+2) . (1+)) 3
                        = 6
于 2010-03-23T00:37:31.410 に答える