2017-03-21 9 views
2

1つの文字列と最大3つの文字列を含むリストをどのように表現できますか?このようなHaskellでこの型を表現する方法

{-# LANGUAGE DeriveFunctor #-} 
{-# LANGUAGE DeriveFoldable #-} 
{-# LANGUAGE DeriveTraversable #-} 
data ListUpTo3 a 
    = Zero 
    | One a 
    | Two a a 
    | Three a a a 
    deriving (Functor, Foldable, Traversable) 

FunctorFoldable、およびTraversableインスタンス(すべてではなく)多くを回復するために利用可能な便利な機能の:

osztaly = [("András", ["mákos", "meggyes", "almás"]), ("Joli", ["túrós"]), ("Anna", ["almás", "almás"]), ("Tamás", []), ("Mari", ["almás", "meggyes"]), ("Vera", [])] 

答えて

7

あなただけのサイズ3を必要とする場合組み込みのリスト

max-3以外のサイズが必要な場合は、これを一般化することができますが、タイプレベルのプログラミングが大幅に増え、タイプの実装者とタイプのユーザーの両方にとってプログラマの努力が大きくなります。

個人的には、おそらくタイプレベルでこの制約を捕捉しようとはしません。次に、最大長3ビットはコンパイラでチェックされません。実装して使用する方がはるかに簡単です。このアイデアについては、ネット上の他の場所のキーワード「スマートコンストラクタ」で詳しく読むことができます。

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 
-- N.B. we do not export the value constructor, only the type constructor 
module UpTo3 (ListUpTo3, fromList, toList) where 

newtype ListUpTo3 a = ListUpTo3 [a] deriving (Functor, Foldable, Traversable) 

fromList :: [a] -> Maybe (ListUpTo3 a) 
fromList xs = if null (drop 3 xs) then Just (ListUpTo3 xs) else Nothing 

toList :: ListUpTo3 a -> [a] 
toList (ListUpTo3 xs) = xs 
+0

'fromList [1 ..]'が発散する代わりにNothingを返すように、エラーの場合は '(_:_:_:_:_)'とパターンマッチングする方がよい。 – amalloy

+0

@amalloyありがとう、私は '3'をより明らかに設定可能にする同様の修正で更新しました。 –

+0

これ以降、 'osztaly'はこの型シグネチャを持つことになるでしょう:' osztaly :: [(String、ListUpTo3 String)] ' –