2016-05-19 7 views
0

ActionThingに適用したい場合があります。値の種類に応じて異なる機能を実行

data Thing = BoxVal Box | BallVal Ball deriving (Show) 
data Box = Box {name :: String}  deriving (Show) 
data Ball = Ball {size :: Int}   deriving (Show) 
data Action = SetName String | Resize Int | ToFoo deriving (Show) 

applyAction :: Thing -> Action -> Maybe String 
applyAction (BoxVal box) a = actionToBox box a 
applyAction (BallVal ball) a = undefined 
applyAction _ _ = Nothing 

actionToBox :: Box -> Action -> Maybe String 
actionToBox b (SetName s) = Just $ s 
actionToBox b (ToFoo)  = Just "foo" 
actionToBox _ _   = Nothing 

作品上記のコード(とは本当にエレガントではない)が、GHCiの約Pattern match(es) are overlappedapplyActionで文句を言います。どのように警告を取得せずに同じ機能を取得するには?

+0

あなたのコードは実際には 'Just'値しか生成しないので、' Maybe'を完全に削除して値を直接返すことができます。 – dfeuer

+0

これはダミーコードです。サポートされていないアクションがある可能性がありますが、Maybeが必要です。 – Paradiesstaub

+1

ハスケルでは、通常、このような事態を避けるためにできる限り多くのことを試しています。関数が 'Thing'を受け入れるならば、それはすべてのThing'sに作用するはずです。時にはこれができないことがあります。可能であれば、エラーを報告するために 'Maybe'などを使用します。それ以外の場合、無効な状態を表現することができなくなり、「アクション」が合計される(つまり、エラーが発生しない)ように、不要なケースを「存在」から削除することができます。最高の慣用的な解決策は、もちろん実際の作業に依存します。 – chi

答えて

4

冗長パターン一致がこれです:

applyAction _ _ = Nothing 

Thingは、2つのコンストラクタ、BoxValBallValを定義し、両方の明示最初の二つのパターンで処理されたものが一致する:

applyAction (BoxVal box) a = actionToBox box a 
applyAction (BallVal ball) a = undefined 

それでapplyAction _ _は不要になります。最初の2つのパターンがすべての可能性にマッチするので、マッチすることはありません。

2

applyActionのクラスを定義し、適切なインスタンスを定義します。

data Thing = BoxVal Box | BallVal Ball deriving (Show) 
data Box = Box {name :: String}  deriving (Show) 
data Ball = Ball {size :: Int}   deriving (Show) 
data Action = SetName String | Resize Int | ToFoo deriving (Show) 

class Actionable x where 
    applyAction :: x -> Action -> Maybe String 

instance Actionable Box where 
    applyAction :: Box -> Action -> Maybe String 
    applyAction b (SetName s) = Just s 
    applyAction b ToFoo = Just "foo" 
    applyAction _ _ = Nothing 

instance Actionable Thing where 
    applyAction :: Thing -> Action -> Maybe String 
    applyAction (BoxVal b) a = applyAction b a 
    applyAction _ _ = undefined 

(クラスが直接重複パターンの問題を解決していませんが、新しい関数名を思い付くする必要からあなたを救うん。applyActionは、その最初の引数の型に応じて、正しいことを行います。)

+0

入力いただきありがとうございます! think-in-haskellの権利を取得するのには時間がかかります。 – Paradiesstaub

+1

@Paradiesstaub:それはありますが、すべてのクラスを率直に定義することは、ハスケルの精神のなかではほとんどありません。実際にいくつかの重要な概念を抽象化している場合にのみ行います。そうでなければ、当初のような単純な関数がしばしばより良いアプローチになります。 – leftaroundabout

関連する問題