2015-12-23 13 views
6

f g x = gのタイプ。 GX

f g x = g . g x 

として定義された関数は、誰もが説明でき、私はそれがタイプ

f :: (t -> t) -> t -> t 

のだろうと思っているだろうタイプ

f :: (b -> a -> b) -> b -> a -> a -> b 

を持っている理由は、私には明確ではありません表現はどのように分解されているのですか?ありがとう!

答えて

11

関数アプリケーションの優先度が最も高いことに注意してください。オペレータは後で来る。

したがって、用語g . g xは、最初にgxに適用し、結果とgを合成します。 xのタイプがbの場合、gのタイプはb -> cである必要があります。 gg x(後者はタイプc)としているため、cbを返す関数型である必要があります。したがって、c = a -> bです。今、gのタイプはb -> a -> bであり、g . g xのタイプはa -> (a -> b)です。 fのタイプは(b -> a -> b) -> b -> a -> a -> bになります。

あなたの代わりに(a -> a) -> a -> aのようなものを望んでいた場合、あなたはアイデアが(.)オペレータを理解することである。この

f g x = g (g x) 
f g x = (g . g) x 
f g x = g . g $ x 
f g = g . g 
+0

のが、その後どのように私はのタイプを推測しますg。 g x? – SendMeMemes

+0

@SendMeMemesは、合成演算子 '(y - > z) - >(x - > y) - > x - > z 'の署名をチェックし、その引数の型、' g'と 'g x'にマッチします。 – lisyarus

2

のいずれかを試みることができるが、それはそれは2つの機能を取る

(.) :: (b -> c) -> (a -> b) -> a -> c 

の種類を持っていますそれぞれと1つのパラメータを使用して構成し、それらを作成した後、を適用した後、コンパイラはgを実際にg :: a -> b -> c 1つの引数を持つ2つの関数をとる(.) :: (b -> c) -> (a -> b) -> a -> cの署名を満たすためです。それ以外の場合、コードはコンパイルされません。

そして、あなたはf :: (t -> t) -> t -> t署名をしたい場合は、最後に、あなたはこのようなものが必要です。だから私は(B - > A - > b)のgは型であることを取得

λ> let applyTwice g = g.g 
λ> :t applyTwice 
applyTwice :: (a -> a) -> a -> a 
λ> applyTwice (*2) 3 
12 
関連する問題