簡體   English   中英

Haskell中State的Functor / Applicative實例

[英]Functor / Applicative instances for State in Haskell

在閱讀(並略讀)Wadler關於monad的論文之后,我決定更仔細地研究這篇論文,為他描述的每個monad定義函子和應用實例。 使用類型同義詞

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

Wadler用於定義狀態monad,我有以下(使用相關的名稱,所以我可以稍后使用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))

但是,由於lambda表達式隱藏在該類型構造函數中,因此GHC中沒有任何內容運行。 現在我看到的唯一解決方案是定義一個函數:

isntThisAnnoying s (S m) = m s

為了將s綁定到'st'並實際返回一個值,例如,

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

還有另一種不使用這些輔助功能的方法嗎?

如果你看這里 ,你會看到他們這樣定義:

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

以便給內在的lambda一個名字。

通常的方法是定義newtype newtype S a = S {runState : State -> (a, State)} 然后你可以編寫runState ts而不是你的isntThisAnnoying s (S m) ,其中tS m相同。
您必須使用newtype因為類型同義詞不能是類型類實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM