Prelude モジュールを読む (6) Data.Semigroup, Data.Monoid

Prelude モジュールを読む (6) Data.Semigroup, Data.Monoid

Prelude モジュールは purescript-prelude パッケージで定義されているモジュールです。

今回は以下の2つのモジュールを確認します。

  • Data.Semigroup
  • Data.Monoid

Data.Semigroup

PureScript Haskell
Semigroup型クラス Semigroup型クラス
append, (<>) (<>)

Semigroup 型クラス

Haskellだと<>だけですね。あと呼び方もmappendなのでちょっと違う。

class Semigroup a where  
  append :: a -> a -> a  

append, (<>)

レコードだけ SemigroupRecord という別の型クラスのメソッドを呼び出していますね。とりあえず今は深追いしないでおこう・・・。(というかレコードも結合できるんだ)

infixr 5 append as <>  

instance semigroupString :: Semigroup String where  
  append = concatString  

instance semigroupUnit :: Semigroup Unit where  
  append _ _ = unit  

instance semigroupVoid :: Semigroup Void where  
  append _ = absurd  

instance semigroupFn :: Semigroup s' => Semigroup (s -> s') where  
  append f g x = f x <> g x  

instance semigroupArray :: Semigroup (Array a) where  
  append = concatArray  

instance semigroupRecord :: (RL.RowToList row list, SemigroupRecord list row row) => Semigroup (Record row) where  
  append = appendRecord (RLProxy :: RLProxy list)  

foreign import concatString :: String -> String -> String  
foreign import concatArray :: forall a. Array a -> Array a -> Array a  

exports.concatString = function (s1) {  
  return function (s2) {  
    return s1 + s2;  
  };  
};  

exports.concatArray = function (xs) {  
  return function (ys) {  
    if (xs.length === 0) return ys;  
    if (ys.length === 0) return xs;  
    return xs.concat(ys);  
  };  
};  

Data.Monoid

PureScript Haskell
Monoid型クラス Monoid型クラス
mempty mempty

Monoid 型クラス

class Semigroup m <= Monoid m where  
  mempty :: m  

mempty

こちらも同じようにレコードは MonoidRecord 型クラスのインスタンスしかだめみたいです。

instance monoidUnit :: Monoid Unit where  
  mempty = unit  

instance monoidOrdering :: Monoid Ordering where  
  mempty = EQ  

instance monoidFn :: Monoid b => Monoid (a -> b) where  
  mempty _ = mempty  

instance monoidString :: Monoid String where  
  mempty = ""  

instance monoidArray :: Monoid (Array a) where  
  mempty = []  

instance monoidRecord :: (RL.RowToList row list, MonoidRecord list row row) => Monoid (Record row) where  
  mempty = memptyRecord (RLProxy :: RLProxy list)  

感想

SemigroupMonoidは最近のHaskellでは良く使いますね。Haskell では mappendMonoid 型クラスにあったりするので PureScript の方がスッキリしてますね。

今まで全然気付いてなかったんですが、インスタンス宣言の仕方がHaskellと違いますね。インスタンス宣言ごとに名前を付けているのかな?

進捗

  • Control.Applicative
  • Control.Apply
  • Control.Bind
  • Control.Category
  • Control.Monad
  • Control.Semigroupoid
  • Data.Boolean
  • Data.BooleanAlgebra
  • Data.Bounded
  • Data.CommutativeRing
  • Data.DivisionRing
  • Data.Eq
  • Data.EuclideanRing
  • Data.Field
  • Data.Function
  • Data.Functor
  • Data.HeytingAlgebra
  • Data.Monoid
  • Data.NaturalTransformation
  • Data.Ord
  • Data.Ordering
  • Data.Ring
  • Data.Semigroup
  • Data.Semiring
  • Data.Show
  • Data.Unit
  • Data.Void