3

私は式のメンバーとして意味していません。私のコード:

data Race = Terran | Zerg | Protoss deriving (Eq, Show, Read);

data MU = MU Race Race deriving (Eq, Show);

この場合、私はインスタンスを定義します(MU Terran Zerg)TvZ関数パターンを一致させることができるように、インスタンスのすべての面で本質的に同一のデータ コンストラクターを作成したいと考えています。

foo TvZ = ...

する代わりに

foo (MU Terran Zerg) = ...

次のように変数に割り当てるとできませんtvZ = (MU Terran Zerg)

私がやりたいもう 1 つのことは、型コンストラクターTTerran同一を作成する場合と同様に、短い形式を作成することです。

最後に、メディバックのスピード ブーストには少しナーフが必要だと思います。

4

3 に答える 3

8

あなたが求めているのは「パターンシノニム」と呼ばれるもので、何度も提案されています。現在は実装されていません。ここここ、および他の多くの場所で提案を表示できます(リンクは hammar の厚意によるものです)。

ただし、解決策として、これも同様に機能します。

foo (MU Terran Zerg) = ...
foo (MU Zerg Terran) = foo $ MU Terran Zerg

見栄えが良くなくても、効果的に同じことを達成します。

于 2013-04-15T04:04:18.933 に答える
6

最初に、次のパターンを使用してみてください (MU Terran Terranその他の自己関係が許可されていると想定しています)。

foo (MU Terran Terran)   = ...
foo (MU Terran Zerg)     = ...
foo (MU Terran Protoss)  = ...
foo (MU Zerg Zerg)       = ...
foo (MU Zerg Protoss)    = ...
foo (MU Protoss Protoss) = ...
foo (MU x y) = foo (MU y x)

そのように定義された関数には細心の注意を払う必要があります。ケースを網羅的に取得しないと、無限ループになるからです。

2 回目の試行: パターンを一般化する試みが行われましたが、思いついた最良の結果は次のとおりです。

forceSymmetric :: (MU -> Maybe r) -> MU -> r
forceSymmetric f = \p -> case f p of
                          Nothing -> fromJust (f (swap p))
                          Just r -> r

foo (MU Terran Terran)   = Just ...
foo (MU Terran Zerg)     = Just ...
foo (MU Terran Protoss)  = Just ...
foo (MU Zerg Zerg)       = Just ...
foo (MU Zerg Protoss)    = Just ...
foo (MU Protoss Protoss) = Just ...
foo (MU x y)             = Nothing

これには、失敗した場合に無限ループではなくエラーが発生するという利点があります。

第三に、より深く試してみてください。問題の核心は、対称性が必要なことです。MUそれがコンストラクタであることを忘れて、単に関数として扱いましょう。この対称法則に従う必要があります。

MU a b == MU b a

==ここで必ずしも型クラスを意味するわけでEqはなく、むしろ相互代用性を意味します。ある式を別の式に置き換えても、プログラムの意味に影響を与えるべきではありません。

ええと、代数データ型にはそのプロパティがありません。のような代数データ型コンストラクタのMU場合、およびのMU a b == MU c d場合のみ。したがって、関数がとを区別できないようにしたい場合は、型を抽象化して、ユーザーがその内部表現を見ることができないようにする必要があります。a == bc == dMU Terran ZergMU Zerg TerranMU

重複を許可して、一度にr個取られるn 個のアイテムの組み合わせの数の式は次のとおりです。と の場合、これは 6 つの組み合わせです。したがって、可能な値が 6 つしかない型、 のような関数、および のような関数を定義する必要があります。これを行う最も簡単な方法は、ソートされたタプルを使用することです。factorial (n + r - 1) / (factorial r * factorial (n - 1))n = 3r = 2MUtoMU :: Race -> Race -> MUmu a b == mu b afromMU :: MU -> (Race, Race)uncurry toMU . fromMU == id

data Race = Terran | Zerg | Protoss deriving (Eq, Show, Read, Ord);

data SortedPair a = SP a a  -- The constructor here needs to be private

makeSortedPair :: Ord a => a -> a -> SortedPair a
makeSortedPair a b | a < b     = SP a b
                   | otherwise = SP b a

breakSortedPair :: SortedPair a a -> (a, a)
breakSortedPair (SP a b) = (a, b)

type MU = SortedPair Race

toMU :: Race -> Race -> MU
toMU = makeSortedPair

fromMU :: MU -> (Race, Race)
fromMU = breakSortedPair

fromMUこれで、が を生成できるが を生成でき(Terran, Zerg)ないことが保証された(Zerg, Terran)ので、上記の最初の 2 つの提案から最終的な「包括的な」ケースを除外できます。(ただし、コンパイラはこれについて何も知らないため、網羅的でないパターンについては依然として文句を言います。)

于 2013-04-15T06:02:05.657 に答える
0

GHC 7.8 から、パターン シノニムを使用できるようになりました。これは、特にこのユースケースを目的とした新しい言語拡張です。

{-# LANGUAGE PatternSynonyms #-}

pattern TvZ :: MU
pattern TvZ = MU Terran Zerg

TvZこれにより、パターン コンテキスト (つまり、マッチング) と式コンテキスト (つまり、新しいMU値の構築) の両方で使用できます。

于 2016-01-16T14:39:00.927 に答える