2017-04-14 3 views
5

は、私は一種[*]の、種類のリストがあるとします。ポリモーフィック機能

let Ts = '[Int, Bool, Char] 

私はタプルのチェーンにこれを変換したい:

type family Tupled (ts :: [*]) z :: * 
type instance Tupled (t ': ts) z = (t, Tupled ts z) 
type instance Tupled '[] z = z 

これまでのところは良い:

> :kind! Tupled Ts() 
Tupled Ts() :: * 
= (Int, (Bool, (Char,()))) 

今、私はその機能を表現するタイプFunを書くことができるようにしたいのですがこの鎖の「底」において多型である。例えば、Fun Ts Tsは、これらのタイプのいずれかで動作するはずです:

(Int, (Bool, (Char, (String,())))) 
(Int, (Bool, (Char, (Word, (ByteString,()))))) 

私はこの試みた:

newtype Fun as bs = Fun 
    { unfun :: forall z. Tupled as z -> Tupled bs z } 

をしかし、それはです。TypeCheckに失敗:

Couldn't match type ‘Tupled bs z’ with ‘Tupled bs z0’ 
NB: ‘Tupled’ is a type function, and may not be injective 
The type variable ‘z0’ is ambiguous 
Expected type: Tupled as z -> Tupled bs z 
    Actual type: Tupled as z0 -> Tupled bs z0 
In the ambiguity check for the type of the constructor ‘Fun’: 
    Fun :: forall z. Tupled as z -> Tupled bs z 
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes 
In the definition of data constructor ‘Fun’ 
In the newtype declaration for ‘Fun’ 

私が使用する勧告を見てきました注入性の問題を避けるためのデータファミリー:

data family Tupled (ts :: [*]) z :: * 
data instance Tupled (t ': ts) z = Cons t (Tupled ts z) 
data instance Tupled '[] z = Nil 

そして実際Funコンパイルを行いますが、私はこのようなタプル、で動作するように探していたときには、ConsNilの地で、私は「スタック」取得のように見える:

Fun $ \ (i, (b, (c, z))) -> (succ i, (not b, (pred c, z))) 

私は回避することができますこれはどういうわけか?

+0

なぜ、 'type fun as bs = forall z? z->タップされたbs z'のようにタップしますか? –

+0

@ Li-yaoXia:「Fun」を「Fun」に引数として渡すことができるように、私はimpredicativityを隠すために「newtype」が必要です。 –

答えて

4

AllowAmbiguousTypesを有効にします。 GHC 8から、あいまい性チェックは完全に余計なものです。なぜなら、(根本的に解決可能な)あいまい性は型アプリケーションで解決できるからです。また、入力アプリケーションがなくてもFunを明示的に使用できるため、曖昧さチェックの誤認にすぎません。

+0

私はこの質問に留意すべきでしたが、これを有効にすると違いはないようです。同じエラーメッセージが表示されます。私は 'lts-8.9' StackリゾルバからGHC 8.0.2を使用しています。 –

+0

この[ファイル](http://lpaste.net/354579)は、GHC 8.0.1と8.0.2の両方で使用できます。私はあなたの側で何が間違っているのか分かりません(また、閉じたタイプのファミリを使用しましたが、開かれた作品も同様です)。 –

+1

Aha、 'newtype Fun as bs = Fun(forall z。...)'型チェック、 '... = Fun {unfun :: forall z。 ...} 'はしません。 'unfun'の*定義*があいまいな*使用サイト*とみなされたので、私は混乱しました。これを別の関数にし、タイプアプリケーション 'unfun :: forallをbs zとして使用する。 fun as bs - > zupledとしてz - > tupled bs z; unfun(Fun f)as = fzは問題を解決する。これを把握してくれてありがとう。 :) –

関連する問題