2011-07-19 8 views
9

考えてみたとき:型クラスのインスタンス型クラスには、次のタイプのクラスを一つだけ

class Listable a where 
    asList :: a t -> [t] 

それは一つのパラメータを持つ型のインスタンスを作成するのは簡単です:

instance Listable [] where 
    asList = id 

instance Listable Maybe where 
    asList (Just x) = [x] 
    asList Nothing = [] 

ここで、2つの同じ型パラメータを持つペアのインスタンスを作成するにはどうすればよいですか?

data V2 a = V2 a a 

v2 (p,q) = V2 p q 

instance Listable V2 where 
    asList (V2 p q) = [p,q] 

今、私はasList $ v2 (47, 11)のようなものを書くことができますが、敗北のこの種の目的:もちろん、私はいくつかの折り返しを行うことができます。

タイプのパラメータが等しいケースにペアのタイプを限定し、それに対してListableのインスタンスを記述する方法はありますか?そうでない場合、通常の回避策は何ですか?

答えて

13

概念的にはこれを行う方法はたくさんあります。残念ながら、それらのほとんどは実際には動作しません。ああ!

instance Listable (\a -> (a, a)) where 
    asList (p, q) = [p,q] 

残念ながら入力レベルをラムダが存在しない:

まず、機能的なプログラマーとして、私はこれがあなた本当にが書きたいものであることを賭けると思います。

type Same2 f a = f a a 

instance Listable (Same2 (,)) where { ... } 

型シノニムが完全に適用されていないため、いずれかの許可されていません。私たちは、型シノニムを使用して上記のラムダの名前のバージョンを書くことができます。我々は一貫性のある種類のを持っていないので、これも失敗してもappが何であるかについて考えなければ

class Listable app f where 
    asList :: app f a -> [a] 

instance Listable __ Maybe where { ... } 

instance Listable __ (,) where { ... } 

:私たちは、代わりに型変数を適用する方法について説明します余分な引数を取るタイプのクラスを想像できますfパラメータ。

実際に動作するものに移動すると、最も一般的な方法はnewtypeの中に型同義語のアプローチをラップし、それに関係するラッピングとアンラッピングを処理することだと思います。

newtype Same2 f a = Same2 (f a a) 

instance Listable (Same2 (,)) where { ... } 

ビットが醜い場合は、実行可能です。タイプコンストラクタのコンポジションやその他のおもちゃをこのように定義し、タイプレベルのポイントを含まない式をフープジャンプボイラープレートの山の下に埋め込んだナットを実行することもできます。最終的アプローチとして

は、あなたも完全に適用されたバージョン、 シングルタイプパラメータからから を行く、「逆に」上記のラムダ式のアプローチをエンコードすることができます。

class Listable t where 
    type ListableElem t :: * 
    asList :: t -> [ListableElem t] 

ビーイングこのようなことをすることができるのは、タイプファミリーにとっての主な動機の1つです。同じことをMPTCと資金で表現することもできますが、それは1)と同等で2)はるかに醜いので、私はそれを書いても構いません。

+0

申し訳ありませんが、試してみるのは怠惰ですが、最後のアプローチでは 'インスタンスのリスト(a、a)'が許されますか? – yatima2975

+0

@ yatima2975:最も外側の型のコンストラクタとして '(、)'と異なるインスタンスを持つ代わりに、yesを返します。おそらくあなたが言及したので、私の答えにその例を入れておくべきでしょう... –

2

これを行うには、いくつかのラッパータイプを定義する必要があります。ただし、newtypeを使用する必要があります。

newtype Foo t a = Foo(t a a) 

instance Listable (Foo (,)) where 
    asList (Foo (a,b)) = [a,b] 
関連する問題