7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

もしもPureScriptのEffectがMonadでなかったら

Last updated at Posted at 2019-04-19
$ purs --version
0.12.5

前置き

EffectはMonadなので例えば以下のようなコードが書けます。

main :: Effect Unit
main = do
  log "hello1"
  log "hello2"
  log "hello3"

do記法はbindの糖衣構文です。

main :: Effect Unit
main = log "hello1" >>= (\_ ->
  log "hello2" >>= (\_ ->
    log "hello3"
  )
)

問い

上記処理を再現する時、EffectはMonadである必要があるか?

  1. Monadでなければならない。
  2. Applicativeであれば十分。
  3. Applyであれば十分。
  4. Functorであれば十分。

答え

Applyであれば十分。

main :: Effect Unit
main = (\_ _ _ -> unit) <$> log "hello1" <*> log "hello2" <*> log "hello3"

ApplicativeとしてのEffect

ado記法

先ほどの例は(\_ _ _ -> unit)と書かなければならないので使い心地が悪いです。
一般に、Applicativeであることを許すとado記法(Applicative Do Notation)が使えます。

main :: Effect Unit
main = ado
  log "hello1"
  log "hello2"
  log "hello3"
  in unit

イメージ的には以下のように脱糖衣されます。

main :: Effect Unit
main = pure (\_ _ _ -> unit) <*> log "hello1" <*> log "hello2" <*> log "hello3"

実際には一般的なApplicativeスタイルのmapapplyで脱糖衣されるようです。

Traversable

class (Functor t, Foldable t) <= Traversable t where
  sequence :: forall a m. Applicative m => t (m a) -> m (t a)

EffectがApplicativeであることを許せば以下のようにも書けます。

main :: Effect Unit
main = traverse_ log ["hello1", "hello2", "hello3"]

Monadの力

前の演算結果を使いたいときには結局bindが必要になります。

randomN :: Effect (Array Int)
randomN = ado -- in以外でx, y, zの値を使うことができない
  x <- randomInt 0 9
  y <- randomInt 10 99
  z <- randomInt 100 999
  in [x, y, z, x, z, z, y]

main :: Effect Unit
main = randomN >>= \x -> logShow x

実行結果例

[3,42,319,3,319,319,42]
7
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?