Home > 一般 > RecordWildCards が便利だなぁ

RecordWildCards が便利だなぁ

Type class で可換半郡を次のように書いていた.

class CommutativeMonoid a where
    oplus :: a -> a -> a,  -- commutative, associative
    identity::a           -- the identity of oplus
data Bag a = Bag [a] deriving (Show,Ord,Read)
instance CommutativeMonoid (Bag a) where
  oplus (Bag a) (Bag b) = Bag (a ++ b)
  identity = Bag []

んで,type class だと不都合が生じたのでレコードで演算をまとめて持ち運ぶようにしたのだけど,定義部分に限っては RecordWildCards を使うとほとんど同じように書ける.演算の集合を定義するという点では type class でもレコードでも手間は大して変わらないっぽいねと. 楽だし簡潔でいい.

data CommutativeMonoid a = CommutativeMonoid {
    oplus :: a -> a -> a,  -- commutative, associative
    identity::a           -- the identity of oplus
    }
data Bag a = Bag [a] deriving (Show,Ord,Read)
bagMonoid = CommutativeMonoid { .. } where   
  oplus (Bag a) (Bag b) = Bag (a ++ b)
  identity = Bag []

インスタンス宣言に同じクラスの別のインスタンスを使う,例えば

instance (CommutativeMonoid a, Ord c) => CommutativeMonoid (Map c a) where
  oplus x y = unionWith oplus x y
  identity = empty

とかも

mapMonoid m = CommutativeMonoid { .. }  where
  oplus x y = let CommutativeMonoid {..} = m in unionWith oplus x y
  identity = empty

と書けばほとんど同じ雰囲気かね.let を内側で使ってあげるのが大事.下のようにやると定義の本体の oplus が新しく定義される oplus になっちゃうのでエラーを食らう.

mapMonoid (CommutativeMonoid {..}) = CommutativeMonoid { .. }  where
  oplus x y = unionWith oplus x y
  identity = empty
★下記に2つの英単語をスペースで区切って入力してください

Home > 一般 > RecordWildCards が便利だなぁ

Search
Feeds

Page Top