モナドの入り口に立つ

Haskellを本格的に勉強しはじめて20日と少し経ち、関数型言語のイメージのようなものは大体つかめて来たと思うので、Haskellerの間で「難関」と言われている「モナド」に挑戦します。

IOや、List、Maybeがモナドだ、というのはいやというほど聞かされていたのですが、仕組みの分らないものを使うのは気が引ける性格なので、思い切って実際にモナドインスタンスを作って動かしてみる事にしました。

module Signal where

data Sig = Red | Yerrow | Blue
instance Show Sig where
    show Red = "Red"
    show Yerrow = "Yerrow"
    show Blue = "Blue"

data Signal a = Signal a
instance Monad Signal where
    (>>=) (Signal a) f = f a
    return a = Signal a

takeSignal :: Signal Sig -> Sig
takeSignal (Signal a) = a

nextSignal :: Sig -> Signal Sig
nextSignal Blue = Signal Yerrow
nextSignal Yerrow = Signal Red
nextSignal Red = Signal Blue

普段対話モードでごにょごにょやる事が多いのでスクリプトの書き方がよく解らなくて七転八倒してしまいました・・・
稚拙なコードではありますが、一応ちゃんと動作します。

*Signal> takeSignal $ return Blue
Blue
*Signal> takeSignal $ return Blue >>= nextSignal
Yerrow
*Signal> takeSignal $ return Blue >>= nextSignal >>= nextSignal
Red
*Signal> takeSignal $ return Blue >>= nextSignal >>= nextSignal >>= nextSignal
Blue

色々とツッコミ所はあると思いますが、ざっくりとしたモナドの「動き」を理解するには、これでOK・・・ですよね?

do記法については、関数型言語を勉強してる時に見た目が手続き指向すぎて敬遠していたのですが、これを足がかりにちゃんと勉強してみようと思います。
これまた車輪の再発明になってしまうのですが、Stateモナドというのを使うと、一時的な副作用を再現できるようですが、実際に活用する前に簡単な副作用を再現してみるのも面白そうです。