/ /なぜ私は型の家族のパターンマッチはできませんか? - haskell、types

なぜ私は型のファミリでパターンマッチを行うことができないのですか? - haskell、types

次のコードを考えてみましょう:

{-# LANGUAGE TypeFamilies #-}

data Twothings a b = Twothings a b

type family Leftthing a where
Leftthing (Twothings a b) = Leftthing a
Leftthing a = a

leftthing :: a -> Leftthing a
leftthing (Twothings a b) = leftthing a
leftthing b = b

次のエラーが発生してコンパイルされません。

Couldn"t match expected type ‘a’
with actual type ‘Twothings a0 t0’
‘a’ is a rigid type variable bound by
the type signature for:
leftthing :: forall a. a -> Leftthing a

それはラインについて不平を言う leftthing (Twothings a b) = leftthing a。私が正しく理解していれば、型変数を統一することはできません a 型シグネチャのコンストラクタの型 Twothings。これは理にかなっているようです。しかしその後、 どのように私は型のファミリを持つ型署名の関数を定義することができます

回答:

回答№1の11

あなたが宣言するとき

leftthing :: a -> Leftthing a

あなたは、 発信者leftthing 何を選ぶか a です。

次に、

leftthing (Twothings a b) = leftthing a

あなたは 推定 彼らは Twothings 必ずしもそうでないので、あなたのプログラムは拒否されます。

あなたはあなたが テストするかどうか 彼らは Twothings タイプですが、いいえ!タイプ情報は実行前に消去されるため、そのようなテストを行う方法はありません。

君は できる 必要な実行時間情報を復元してください。まず、あなたとあなたの間の不一致を修正しましょう。 Leftthing そして leftthing

type family Leftthing a where
Leftthing (Twothings a b) = Leftthing{-you forgot the recursion!-} a
Leftthing a = a

目撃者のGADTを定義して Twothingネス。

data IsItTwothings :: * -> * where
YesItIs   :: IsItTwothings a -> IsItTwothings (Twothings a b)
NoItIsn"t :: Leftthing a ~ a => IsItTwothings a
-- ^^^^^^^^^^^^^^^ this constraint will hold for any type
-- which is *definitely not* a Twothings type

そして証人を議論として渡すことができます:

leftthing :: IsItTwothings a -> a -> Leftthing a
leftthing (YesItIs r) (Twothings a b) = leftthing r a
leftthing NoItIsn"t   b               = b

実際には、目撃者は左ネストされた数の単項エンコーディングです Twothingsあなたのタイプのルートに。これは実行時に正しい解凍量を決定するのに十分な情報です。

> leftthing (YesItIs (YesItIs NoItIsn"t)) (Twothings (Twothings True 11) (Twothings "strange" [42]))
True

要約すると、パターンごとにタイプを見つけることはできません値の照合。むしろ、パターンマッチングを行うために型を知る必要があります(型がメモリレイアウトを決定し、実行時型タグがないため)。型に直接パターンマッチングすることはできません(マッチしないため)。型構造の実行時のエビデンスとして機能するデータ型を構築し、代わりにその型構造に一致させることができます。

おそらく、ある日、あなたがそれをタイプするとあなたのプログラムはうまくいくでしょう

leftthing :: pi a. a -> Leftthing a

どこで pi 隠された型の引数が消去されず、実行時に渡されて一致することを示す依存量子です。その日はまだ来ていないが、私はそうなると思う。