は、私は一種[*]
の、種類のリストがあるとします。ポリモーフィック機能
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
コンパイルを行いますが、私はこのようなタプル、で動作するように探していたときには、Cons
とNil
の地で、私は「スタック」取得のように見える:
Fun $ \ (i, (b, (c, z))) -> (succ i, (not b, (pred c, z)))
私は回避することができますこれはどういうわけか?
なぜ、 'type fun as bs = forall z? z->タップされたbs z'のようにタップしますか? –
@ Li-yaoXia:「Fun」を「Fun」に引数として渡すことができるように、私はimpredicativityを隠すために「newtype」が必要です。 –