Prelude モジュールを読む (3) Data.Boolean, Data.Function, Control.Applicative, Control.Bind

Prelude モジュールを読む (3) Data.Boolean, Data.Function, Control.Applicative, Control.Bind

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

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

  • Data.Boolean
  • Data.Function
  • Control.Applicative
  • Control.Bind

Data.Boolean

PureScript Haskell
otherwise otherwise

otherwise

otherwise :: Boolean  
otherwise = true  

Data.Function

PureScript Haskell
flip flip
const const
apply, ($) ($)

flip

flip :: forall a b c. (a -> b -> c) -> b -> a -> c  
flip f b a = f a b  

const

const :: forall a b. a -> b -> a  
const a _ = a  

apply, ($)

apply :: forall a b. (a -> b) -> a -> b  
apply f x = f x  

infixr 0 apply as $  

Control.Applicative

PureScript Haskell
Applicative 型クラス Applicative
when Control.Monad.when
unless Control.Monad.unless
liftA1 Control.Applicative.liftA

Applicative 型クラス

Haskellとの違いは

  • Apply型クラスがスーパークラスになっている
  • pureのみを定義すれば良い

という点ですね。

class Apply f <= Applicative f where  
  pure :: forall a. a -> f a  

instance applicativeFn :: Applicative ((->) r) where  
  pure x _ = x  

instance applicativeArray :: Applicative Array where  
  pure x = [x]  

when

Haskellでも良く使うのでPreludeに入っているのは嬉しいですね。

when :: forall m. Applicative m => Boolean -> m Unit -> m Unit  
when true m = m  
when false _ = pure unit  

unless

条件分岐がwhenの逆バージョンですね。

unless :: forall m. Applicative m => Boolean -> m Unit -> m Unit  
unless false m = m  
unless true _ = pure unit  

liftA1

個人的にはあんまり使わないかも。<$><*>で書いてしまう。

liftA1 :: forall f a b. Applicative f => (a -> b) -> f a -> f b  
liftA1 f a = pure f <*> a  

Control.Bind

これはHaskellに無いですね。

PureScript Haskell
Bind 型クラス -
bind, (>>=) (>>=)
Discard 型クラス -
discard -
join Control.Monad.join
ifM Control.Monad.Extra Extra (extra)
(>=>) Control.Monad.(>=>)
(=<<) (=<<)
(<=<) Control.Monad.(<=<)

Bind 型クラス, bind, (>>=)

HaskellでいうところのMonad型クラスの>>=を提供する型クラスですね。

class Apply m <= Bind m where  
  bind :: forall a b. m a -> (a -> m b) -> m b  

infixl 1 bind as >>=  

instance bindFn :: Bind ((->) r) where  
  bind m f x = f (m x) x  

instance bindArray :: Bind Array where  
  bind = arrayBind  

foreign import arrayBind :: forall a b. Array a -> (a -> Array b) -> Array b  

exports.arrayBind = function (arr) {  
  return function (f) {  
    var result = [];  
    for (var i = 0, l = arr.length; i < l; i++) {  
      Array.prototype.push.apply(result, f(arr[i]));  
    }  
    return result;  
  };  
};  

この型クラスのインスタンスになっていればdo記法が使えるっぽいですね。

Discard 型クラス, discard

Haskellに無いやつですね。今の所、使い道は良くわからない・・・。

class Discard a where  
  discard :: forall f b. Bind f => f a -> (a -> f b) -> f b  

instance discardUnit :: Discard Unit where  
  discard = bind  

join

join :: forall a m. Bind m => m (m a) -> m a  
join m = m >>= identity  

ifM

Haskellではextraパッケージで定義されていますね。コードの可読性が落ちる気がするので、個人的にはあまり使わないです。

ifM :: forall a m. Bind m => m Boolean -> m a -> m a -> m a  
ifM cond t f = cond >>= \cond' -> if cond' then t else f  

(>=>)

composeKleisli :: forall a b c m. Bind m => (a -> m b) -> (b -> m c) -> a -> m c  
composeKleisli f g a = f a >>= g  

infixr 1 composeKleisli as >=>  

(=<<)

bindFlipped :: forall m a b. Bind m => (a -> m b) -> m a -> m b  
bindFlipped = flip bind  

infixr 1 bindFlipped as =<<  

(<=<)

composeKleisliFlipped :: forall a b c m. Bind m => (b -> m c) -> (a -> m b) -> a -> m c  
composeKleisliFlipped f g a = f =<< g a  

infixr 1 composeKleisliFlipped as <=<  

感想

今回はHaskellにある関数が多かったためサクサク読めました。join, when, unless などがPreludeに入っているのは良いですね。

どんどん読んでいこー。

進捗

  • 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