8

カードの手札を表す ADT を Haskell で書いています。(Suit,Face)私の問題は、カードを表す数をハンドを表す 5に制限したいということです。

data Card = Hand [(Suit,Face)]

私がやろうとしたのはこれでしたが、うまくいきません。

data Card = Hand [(Suit,Face),(Suit,Face),(Suit,Face),(Suit,Face),(Suit,Face)]

私の質問は: タプルの数を 5 に制限するにはどうすればよいですか?

4

3 に答える 3

14

5タプルに基づくソリューションを使用する場合(他の回答で示唆されているように)、必要なすべての折りたたみ/トラバース機能を引き続き使用できることを追加したいと思います。特に、最初に定義する

import Control.Applicative
import Data.Foldable
import Data.Traversable

data Tuple5 a = Tuple5 a a a a a

その上で折り畳みトラバース操作を定義します。

instance Traversable Tuple5 where
    traverse f (Tuple5 a b c d e)
            = Tuple5 <$> f a <*> f b <*> f c <*> f d <*> f e
instance Foldable Tuple5 where
    foldMap = foldMapDefault
instance Functor Tuple5 where
    fmap    = fmapDefault

次に、あなたが持つことができます

data Hand = Hand (Tuple5 Card)

Foldable/ Traversable/の任意のメソッドを使用して、構造を折り畳む/トラバースしますFunctor


更新:最近、次のような同種タプルのエイリアスを定義する小さなライブラリtuples-homogenous-h98を作成しました。newtype

newtype Tuple5 a = Tuple5 { untuple5 :: (a,a,a,a,a) }

Traversable適切な、FoldableFunctorApplicativeおよびMonadインスタンスを追加します。

于 2013-01-27T14:05:24.160 に答える
5

どうですか

data Card = Hand (Suit, Face) (Suit, Face) (Suit, Face) (Suit, Face) (Suit, Face)

または、本当にリストを使用したい場合(つまり、15枚のカードのハンドが必要な場合、私の提案は非常にばかげたものになります)、コンストラクターを使用しないdata Card = Hand [(Suit, Face)]ようにユーザーに指示し、代わりに「スマートコンストラクター」を提供できます。お気に入り

fromList :: [(Suit, Face]) -> Maybe Card
fromList xs 
        | length xs == 5 = Just (Hand xs)
        | otherwise      = Nothing

次に、コンストラクター自体を使用可能にして、「提供されたリストに正確に5つの要素が含まれていることが保証されている場合にのみ使用する」などの警告を表示することもできます。

ちなみに、データ型CardとコンストラクターHandの名前は少し直感に反していませんか?あなたの場合、データ型を呼び出すべきだと思いHandます。は-ペアCardの優れたエイリアスなので、とを行うことができます。SuitFacetype Card = (Suit, Face)data Hand = Hand [Card]

于 2013-01-27T13:02:07.690 に答える
5

カードのタイプと、5つのカード要素を持つ手のタイプを作成できます。

type Card = (Suit, Face)
data Hand = Hand Card Card Card Card Card
于 2013-01-27T13:02:58.047 に答える