2017-09-22 11 views
0

私は、複数の引数をとる関数gを持つ関数fを作成する関数を作成しようとしています。 Iは、F、G、次いでN引数(入力を保存するために)、以下を取る関数を生成する関数を定義しようとすると、しかしさらに別の無限型エラー

*Main> (lift $ lift $ lift $ lift $ lift $ c) (\x -> x+2) (\x y z a b c -> x*y*z-(a*b*c)) 1 2 3 4 5 6 
-112 

c :: (a -> b) -> (c -> a) -> c -> b 
c x y z = x(y(z)) 
lift = c c 

(lift $ lift $ lift ... c)は、所望の機能を作成しますエラーが発生します:

cn 1 = c 
cn k = lift (cn(k-1)) 
<interactive>:9:1: error: 
    * Occurs check: cannot construct the infinite type: a ~ c0 -> a 
     Expected type: t -> (a -> b) -> a -> b 
     Actual type: t -> (a -> b) -> (c0 -> a) -> c0 -> b 
    * Relevant bindings include 
     cn :: t -> (a -> b) -> a -> b (bound at <interactive>:9:1) 

なぜこのエラーが発生し、どのように解決できますか?

+0

typeclassトリックを使わずにHaskellの引数に任意の数を取る関数を定義することはできません。あなたは可変引数を取る関数を作ろうとしており、GHCは適切な型を推論することができません。 – AJFarmar

+3

'cn'が持つべき型を書き留めてみましたか? –

+1

"複数の引数をとる関数g"は実際にはHaskellの場合、ちょうど1つの引数をとり、別の関数を返す関数です。 2つの引数を持つ関数と関数を返す1つの引数を持つ関数を区別する方法はありません。このため、あなたがしようとしているような一般的な構成機能を定義するのは難しいです。 – chi

答えて

2

ハスケルでは、型変換なしで多変数関数を作成することはできません。

1つまたは2つの引数を取る関数を作成しようとすると、タイプa -> ba -> p -> bの関数を作成しようとします。したがって、コンパイラはタイプbp -> bと等価であることを推測しなければならないので、関数のタイプはa -> p -> p -> p -> ...になります。つまり、無限のタイプです。

この機能を実行しようとすると、同様の問題が発生します。最初の行は大丈夫です:

cn 1 = c 

これはcn :: Int -> (b -> c) -> (a -> b) -> a -> cのようなものです。我々はcn :: Int -> (b -> c) -> (a -> b) -> a -> cは、我々はcn (k-1) :: (b -> c) -> (a -> b) -> a -> cことを推測しなければならないことを知っているので

cn k = lift (cn (k-1)) 

:しかし、我々は今、2行目の問題を抱えています。しかし、lift :: (x -> y -> z) -> x -> (w -> y) -> w -> z以降、戻り値は元の型宣言と衝突する型(b -> c) -> (w -> a -> b) -> w -> cでなければなりません。

TL; DR:値を介してHaskell関数/値の型を変更することはできません。つまり、特定のトリックなしに多変数関数を書くことはできません。

関連する問題