1

GHCi のリストから最後の項目を削除するには、リストを逆にし、テールを取得してから、もう一度逆にします。例えば、

reverse(tail(reverse([1,2,3,4])))

そこには非常に多くのブラケットがあるので、代わりに関数合成を使用するように変更すると思いました。ただし、これを試してみると、次のエラーが発生します。

Prelude> reverse . tail. reverse [1,2,3,4]

<interactive>:2:17:
    Couldn't match expected type `a0 -> [a1]' with actual type `[a2]'
    In the return type of a call of `reverse'
    Probable cause: `reverse' is applied to too many arguments
    In the second argument of `(.)', namely `reverse [1, 2, 3, 4]'
    In the second argument of `(.)', namely
      `tail . reverse [1, 2, 3, 4]'

これは を構成するのが好きではないことを意味していると思うreverse [1,2,3,4]ので、括弧で囲んでみましたが、同じエラーが発生します。

Prelude> reverse . tail. (reverse [1,2,3,4])

<interactive>:3:18:
    Couldn't match expected type `a0 -> [a1]' with actual type `[a2]'
    In the return type of a call of `reverse'
    Probable cause: `reverse' is applied to too many arguments
    In the second argument of `(.)', namely `(reverse [1, 2, 3, 4])'
    In the second argument of `(.)', namely
      `tail . (reverse [1, 2, 3, 4])'

しかし、次のようにすると正しく動作します。

Prelude> let f = reverse . tail . reverse
Prelude> f [1,2,3,4]
[1,2,3]

このエラーの原因は何ですか? let バインディングがこれを停止するのはなぜですか?

4

2 に答える 2

8

type of を見る.と、両方のオペランドが関数 (構成できるように適切な型) であることが期待されていることがわかります。

Prelude> :i (.)
(.) :: (b -> c) -> (a -> b) -> a -> c   -- Defined in `GHC.Base'
infixr 9 .

現在、関数適用はどの中置演算子よりも優先されるため、

Prelude> reverse . tail . reverse [1,2,3,4]

になる

Prelude> reverse . tail . (reverse [1,2,3,4])

コンポジションを適用しようとすると、タイプが間違っています。合成を正しく行うには、明示的な括弧を指定して実行できる関数適用よりも合成を明示的に優先する必要があります。

Prelude> (reverse . tail . reverse) [1,2,3,4]

このソリューションは機能しますが、ハスケラーは括弧の使用を嫌います。$このような場所であなたを救い、括弧を使用するよりもコードを読みやすくする別の演算子があります。の種類を見ると、$

Prelude> :i ($)
($) :: (a -> b) -> a -> b       -- Defined in `GHC.Base'
infixr 0 $

その優先度 (0) が構成の優先度 (9) よりも低く、必要な効果が得られることがはっきりとわかります。最後の関数適用の優先順位を下げるか、関数構成を に置き換えることができます$

Prelude> reverse . tail . reverse $ [1,2,3,4]
Prelude> reverse . tail $ reverse [1,2,3,4]
Prelude> reverse $ tail $ reverse [1,2,3,4]

の最初のオペランドは$関数であり、他のオペランドは正しい型の値であるため、これはまったく問題ありません。

于 2013-01-09T13:05:58.807 に答える
4

let関数が で構成され、.関数構成の結果への引数としてリストが与えられる場合:

(reverse . tail . reverse) [1,2,3,4]

それ以外の場合、リストは引数として与えられ、reverseその結果は他の関数で構成されます:

reverse . tail . (reverse [1,2,3,4])

によって返される反転リストはreverse [1,2,3,4]関数ではないため、これを の引数として使用すると.型エラーが発生します。

于 2013-01-09T13:02:59.430 に答える