Haskell Language
部分的なアプリケーション
サーチ…
備考
初心者の間違いを解消しましょう。
あなたは次のような機能に遭遇したかもしれません:
max :: (Ord a) => a -> a -> a
max m n
| m >= n = m
| otherwise = n
初心者は、典型的には、表示されますmax :: (Ord a) => a -> a -> a
タイプの二つの引数(値)をとる関数としてa
し、型の値を返し。 a
しかし、実際に起こっていることは、 max
がタイプa
1つの引数をとり 、タイプa -> a
関数を返す a -> a
です。この関数は、型の引数取りa
、タイプの最終値を返しa
。
実際、 max
はmax :: (Ord a) => a -> (a -> a)
と書くことができます。
max
の型シグネチャを考えてみましょう:
Prelude> :t max
max :: Ord a => a -> a -> a
Prelude> :t (max 75)
(max 75) :: (Num a, Ord a) => a -> a
Prelude> :t (max "Fury Road")
(max "Fury Road") :: [Char] -> [Char]
Prelude> :t (max "Fury Road" "Furiosa")
(max "Fury Road" "Furiosa") :: [Char]
max 75
とmax "Fury Road"
は機能のようには見えないかもしれませんが、実際はそうです。
混乱は、数学やその他の一般的なプログラミング言語では、複数の引数を取る関数を持つことが許されているという事実に由来します。しかし、Haskellでは、 関数は1つの引数しか取ることができず 、 a
ような値やa -> a
ような関数を返すことができます。
部分的に適用された機能の追加
部分的なアプリケーションを使って最初の引数を "ロック"することができます。 1つの引数を適用すると、結果を返す前にもう1つの引数が必要な関数が残されます。
(+) :: Int -> Int -> Int
addOne :: Int -> Int
addOne = (+) 1
次に、 addOne
を使ってInt
1を加えることができます。
> addOne 5
6
> map addOne [1,2,3]
[2,3,4]
部分的に適用された関数の返却
部分的に適用された関数を返すことは、簡潔なコードを書くための1つの手法です。
add :: Int -> Int -> Int
add x = (+x)
add 5 2
この例では(+ x)は部分的に適用される関数です。 add関数の2番目のパラメーターは、関数定義で指定する必要はないことに注意してください。
add 5 2
を呼び出した結果は7です。
セクション
セクション分割は、中断演算子に部分的に引数を適用する簡潔な方法です。
たとえば、単語の末尾に "ing"を追加する関数を記述したい場合は、セクションを使用して関数を簡潔に定義することができます。
> (++ "ing") "laugh"
"laughing"
第2引数を部分的にどのように適用したかに注目してください。通常、指定された順序で引数を部分的にしか適用できません。
左セクションを使用して、最初の引数を部分的に適用することもできます。
> ("re" ++) "do"
"redo"
我々は等価的に通常の接頭辞部分アプリケーションを使用してこれを書くことができます:
> ((++) "re") "do"
"redo"
減算に関する注意
初心者は間違って否定をすることが多い。
> map (-1) [1,2,3]
***error: Could not deduce...
これは、動作しない-1
リテラルとして解析され-1
なく切片化演算子よりも-
に適用される1
。 subtract
関数は、この問題を回避するために存在します。
> map (subtract 1) [1,2,3]
[0,1,2]