12

モナドに関する Wadler の論文を読んだ (そしてそのいくつかのセクションをざっと読んだ) 後、私は論文をより綿密に調べ、彼が記述した各モナドのファンクターとアプリケーションのインスタンスを定義することにしました。型シノニムの使用

type M a = State -> (a, State)
type State = Int

Wadler は状態モナドを定義するために使用します。私は次のようにしています (関連する名前を使用して、後で newtype 宣言で定義できるようにします)。

fmap' :: (a -> b) -> M a -> M b
fmap' f m = \st -> let (a, s) = m st in (f a, s)

pure' :: a -> M a
pure' a = \st -> (a, st)

(<@>) :: M (a -> b) -> M a -> M b
sf <@> sv = \st -> let (f, st1) = sf st
                       (a, st2) = sv st1
                    in (f a, st2)

return' :: a -> M a
return' a = pure' a

bind :: M a -> (a -> M b) -> M b
m `bind` f = \st -> let (a, st1) = m st
                        (b, st2) = f a st1
                     in (b, st2)

newtype 宣言で型コンストラクターの使用に切り替えると、たとえば、

newtype S a = S (State -> (a, State))

すべてがバラバラになります。すべてがわずかな変更にすぎません。たとえば、

instance Functor S where
 fmap f (S m) = S (\st -> let (a, s) = m st in (f a, s)) 

instance Applicative S where
 pure a = S (\st -> (a, st))

ただし、ラムダ式がその型コンストラクター内に隠されているため、GHC では何も実行されません。今私が見る唯一の解決策は、関数を定義することです:

isntThisAnnoying s (S m) = m s

s を 'st' にバインドし、実際に値を返すには、たとえば、

fmap f m = S (\st -> let (a, s) = isntThisAnnoying st m in (f a, s))

これらの補助機能を使用しない別の方法はありますか?

4

2 に答える 2

11

ここを見ると、次のように定義されていることがわかります。

newtype State s a = State { runState :: (s -> (a,s)) }

内部ラムダに名前を付けるために。

于 2010-08-20T18:45:25.453 に答える
5

通常の方法は、 を定義することnewtype newtype S a = S {runState : State -> (a, State)}です。次に、 your の代わりにwhere is is same とisntThisAnnoying s (S m)書くことができます。型シノニムは型クラス インスタンスにできないため 、 a を使用する必要があります。runState t stS m
newtype

于 2010-08-20T18:46:51.033 に答える