次のデータ型と型クラス(適切な言語拡張子を持つ)があると想像してください。
data Zero=Zero
data Succ n = Succ n
class Countable t where
count :: t -> Int
instance Countable Zero where
count Zero = 0
instance (Countable n) => Countable (Succ n) where
count (Succ n) = 1 + count n
整数から、適切な型クラスインスタンスのインスタンスを私に与える関数を書くことは可能でしょうか?基本的にはf
、count (f n) = n
私の試みは次のようなものでしたが、これによりコンパイル時にいくつかのタイプエラーが発生します。
f::(Countable k)=> Int -> k
f 0 = Zero
f n = Succ $ f (n-1)
解決策を探しているときに依存型に関する議論に何度も遭遇しましたが、それらの議論を自分のユースケースにマッピングすることはまだできていません。
コンテキスト:これにより、「なぜこれを実行したいのか」というタイプの質問がたくさん発生することを理解しているためです。
私は現在Data.HList
、異種リストを操作するためにパッケージを使用しています。shuffle
このライブラリでは、整数を指定すると、リストn
のth要素を最後にシフトする関数を作成したいと思います。n
たとえば、もし持っていたら、与えl=1:"Hello":32:500
たいと思います。shuffle 1 l
1:32:500:"Hello"
私はshuffle0
次のユースケースに答える特殊な関数を書くことができましたshuffle 0
:
shuffle0 ::(HAppend rest (HCons fst HNil) l')=>HCons fst rest -> l'
shuffle0 (HCons fst rest) = hAppend rest (HCons fst HNil)
next
また、次のように、関数を「ラップ」するこの関数を作成しましたnext (shuffle n) = shuffle (n+1)
。
next :: (forall l l'. l -> l') -> (forall e l l'.(HCons e l) -> (HCons e l'))
next f = \(HCons e l)-> HCons e $ (f l)
型署名が役に立たないように感じます。つまり、長さのエンコードがありません(問題が発生する可能性があります)。
shuffle 0=shuffle0
shuffle n= next (shuffle (n-1))
GHCは、シャッフルのタイプを推測できないことに不満を持っています。
タイプはおそらく十分に確立されていないので、これは私を本当に驚かせません。
直感的には、リストの長さについて言及する必要があると思います。type関数を使用して特定のHListタイプの長さを取得できます。HLength
いくつかの適切に選択された制約を使用して、シャッフルを書き直し、サウンドになります(少なくとも私は思います)。
問題は、選択した長さのタイプレベルのバージョンを取得して、呼び出しで使用できるようにする必要があることです。これでうまくいくかどうかさえわかりませんが、もっとチャンスがあると思います。