2016-11-23 7 views
8

私はタイプレベルのリスト上のタイプの家族をマッピングする(singletonsライブラリから抜粋)この最小限の作業例を持っています。なぜこのコードは「型ファミリの飽和要件」に違反しないのですか?

ghci> :set -XDataKinds 
ghci> :kind! Map (TyCon1 Flip) '[Char,Int] 
Map (TyCon1 Flip) '[Char,Int] :: [*] 
= '[Int, Char] 

コードを説明します

{-# language PolyKinds #-} 
{-# language DataKinds #-} 
{-# language TypeFamilies #-} 
{-# language TypeOperators #-} 

data TyFun :: * -> * -> * 

data TyCon1 :: (k1 -> k2) -> (TyFun k1 k2 -> *) 

type family Apply (f :: TyFun k1 k2 -> *) (x :: k1) :: k2 
type instance Apply (TyCon1 f) x = f x 

type family Map (f :: TyFun a b -> *) (as :: [a]) :: [b] where 
    Map f '[] = '[] 
    Map f (x ': xs) = Apply f x ': Map f xs 

type family Flip t :: * where 
    Flip Int = Char 
    Flip Char = Int  

動作するようです投稿の中でDefunctionalization for the win。これは、 "GHCは型変数を型族と統一させません"という事実を回避する方法です。これは「タイプファミリの飽和要件」と呼ばれます。

私の疑いがある:私たち「実行」:kind! Map (TyCon1 Flip) '[Char,Int]ラインtype instance Apply (TyCon1 f) x = f xで、fは、私たちのFlip型家族と照合されます、と思われるとき。なぜこれは飽和要件を侵害しないのですか?

+0

私はそれが動作するとは思わない。しかし、類義語は型チェックの際に拡張されるので完全に無害です。 – dfeuer

+1

私はあなたが本当に 'Flip'のために' apply'インスタンスを使って機能停止シンボルを提供することになっていると思います。 'TyCon1'は型コンストラクタに適用されることを意図しています。ところで、これはGHCのどのバージョンですか? – dfeuer

+1

@dfeuer GHC 8.0.1を使用しています。どうやら、ghciで ':kind! 'を使ったときに動作するようですが、' Boo = Map(TyCon1 Flip)' [Char、Int] 'のようなものをスクリプトに追加しようとすると、コンパイルエラーが出ます。 – danidiaz

答えて

2

私は自分の質問にdfeuerとuser2407038のコメントから情報を得て答えています。

私のコードが飽和要件を侵していたことが判明しました。 ghciの:kind!という奇妙な動作(バグ?)のために私はエラーを見つけられませんでした。しかし、ファイルをhsファイルに書き込むと、コンパイルエラーが発生します。

は、タイプファミリではなく、タイプ変数との統合に問題がないMaybeのような通常型コンストラクタをラップします。たとえば、type Foo = Map (TyCon1 Maybe) '[Char,Int]はうまく動作します。

タイプファミリでは、それぞれに特殊な補助タイプを定義し、そのタイプのApplyインスタンスを定義する必要があります。このように:

data FlipSym :: TyFun * * -> * 
type instance Apply FlipSym x = Flip x 

type Boo = Map FlipSym '[Char,Int] 

お知らせそのFlipタイプの家族はどのようなタイプの変数に統一されていないこの方法。

+1

申し訳ありませんが、自分自身で答えを出すことに慣れていませんでした。あなたのものは少なくとも私が書いたものと同じくらい良いものです。 1つのニットを選びたい:私はその家族のためにフリップという名前が好きではない。私の考えでは、その名前は常にnewtype Flip(f :: j - > k - > *)(x :: j)= Flip {unFlip :: f x y} 'と定義されています。その結果得られる 'flip 'の型レベルのバージョンはかなり頻繁に現れ、型同義語のバージョン(' Type Flip f y x = f x y')が役に立たない文脈で一般的に現れます。 – dfeuer

関連する問題