Haskellはリストの種類を数え
-
20-09-2019 - |
質問
だから、楽しみのためだけに、私はペアノ番号を使用して、HaskellでCountedListタイプでプレーしてきました そして、スマートコンストラクタはします。
タイプセーフhead
とtail
はちょうど私には本当にクールなようです。
そして、私は私が行う方法を知っているものの限界に達したと思う。
{-# LANGUAGE EmptyDataDecls #-}
module CountedList (
Zero, Succ, CountedList,
toList, ofList,
empty, cons, uncons,
head, tail,
fmap, map, foldl, foldr, filter
) where
import qualified List (foldr, foldl, filter)
import Prelude hiding (map, head, foldl, foldr, tail, filter)
data Zero
data Succ n
data CountedList n a = CL [a]
toList :: CountedList n a -> [a]
toList (CL as) = as
ofList :: [a] -> CountedList n a
ofList [] = empty
ofList (a:as) = cons a $ ofList as
empty :: CountedList Zero a
empty = CL []
cons :: a -> CountedList n a -> CountedList (Succ n) a
cons a = CL . (a:) . toList
uncons :: CountedList (Succ n) a -> (a, CountedList n a)
uncons (CL (a:as)) = (a, CL as)
head :: CountedList (Succ n) a -> a
head = fst . uncons
tail :: CountedList (Succ n) a -> CountedList n a
tail = snd . uncons
instance Functor (CountedList n) where
fmap f = CL . fmap f . toList
map :: (a -> b) -> CountedList n a -> CountedList n b
map = fmap
foldl :: (a -> b -> a) -> a -> CountedList n b -> a
foldl f a = List.foldl f a . toList
foldr :: (a -> b -> b) -> b -> CountedList n a -> b
foldr f b = List.foldr f b . toList
filter :: (a -> Bool) -> CountedList n a -> CountedList m a
filter p = ofList . List.filter p . toList
(任意の転記ミスのため申し訳ありません - 私はもともと私のHaskellのコンパイラは現在ダウンしている/ワットでこれを書いているマシン)。
私がやったのほとんどは、W / O問題コンパイルが、私はofList
とfilter
の問題に遭遇します。私は理由を理解すると思う - 私はofList :: [a] -> CountedList n a
を言うとき、私はofList :: forall n . [a] -> CountedList n a
を言っている - 作成したリストは、任意の数のタイプのものとすることができるという。私が書きたいのは、擬似型ofList :: exists n . [a] -> CountedList n a
のと同等ですが、私は方法がわからない。
私が想像してるように私はofList
とfilter
機能を書いてみましょうだろうか私はこれで何ができるかの限界に達している回避策はありますか?私は私が欠けていることをを実存的なタイプといくつかのトリックがあることを意味しています。
解決
あなたが書き込むことはできません。
ofList :: [a] -> (exists n. CountedList n a) -- wrong
しかし、あなたが書くことができます。
withCountedList :: [a] -> (forall n. CountedList n a -> b) -> b
、それにあなたがいる限り、その種類は、リストの長さとは無関係であるとして、ofList
の結果で行われているだろうか。
ところで、あなたはリストの型は型システムではその長さに対応することを不変性を確保することができ、かつスマートコンストラクタに依存していません。
{-# LANGUAGE GADTs #-}
data CountedList n a where
Empty :: CountedList Zero a
Cons :: a -> CountedList n a -> CountedList (Succ n) a
他のヒント
あなたはofList
を定義したり、彼らは実行時の値を持つ交絡タイプ・レベルでチェックしているので、この方法をfilter
することはできません。具体的には、結果のタイプに、CountedList n a
、型n
は、コンパイル時に決定されなければなりません。暗黙の欲望がn
が最初の引数であるリストの長さに相応すべきであるということです。しかし、それは明らかに、実行時まで知られてすることはできません。
さて、型クラスを定義することが可能に数え言い、その後、(適切なHaskellの拡張子を持つ)、これらのように定義します。
ofList :: [a] -> (forall n. (CountedListable CountedList n) => CountedList n a)
しかし、あなたはそのCountedListable
は、カウントを抽出するだろうサポートできるだけの操作ので、このような結果と何も苦労し、持っていると思います。あなたは、ヘッドがhead
のすべてのインスタンスのために定義することができませんでしたので、このような値のCountedListable
を取得すると言うことができませんでした。