2017-05-26 41 views
4

我對Haskell有點新鮮,而且我在國家monad方面遇到了一些麻煩。Haskell - 我將如何運行狀態單子列表?

我已經創建了以下類型。 Stat a有爲它創建的monoid,functor,applicative和monad實例。

「主」式的在我的計劃是動物,它有很多爭論:

data Creature = Creature { 
    strength :: Stat Integer, 
    dexterity :: Stat Integer, 
    ... 
} 

data Stat a = Stat { 
    modifiers :: [StatModifier], 
    stat  :: a 
} 

data StatModifier = StatModifier { 
    modifierType :: ModifierType, 
    value  :: Integer 
} 

data ModifierType = 
    Enhancement 
    | Morale 
    | ... 

有很多事情可以發生在一個生物。我選擇了代表與國家單子那些事:

anyPossibleChange :: State Creature Creature 

這可能是破壞正在做生物,增加對生物的實力,基本上什麼。任何事情的可能性都讓我覺得國家monad在這裏是個不錯的選擇。我將接受一個處於原始狀態的生物,執行一些修改,並將原始狀態和新狀態返回到一個元組中。

原來的狀態可能是:

Creature { 
    strength = Stat [] 10, 
    dexterity = Stat [] 10 
} 

結束狀態可能是:

Creature { 
    strength = Stat [StatModifier Enhancement 2] 10, 
    dexterity = Stat [StatModifier Enhancement 4, StatModifier Morale 2] 10 
} 

我想建的所有更改列表的動物需要經過,然後運行通過所有這些變化的生物。

這是我想到的簽名,但我遇到了實現問題。我對它有所不同。

applyChanges :: Creature -> [State Creature Creature] -> Creature 

我覺得我應該能夠摺疊做到這一點,可能FoldM但我的大腦是越來越掛了周圍的類型。

一個好的實現會是什麼?

+2

什麼是開始狀態?列表爲空時應該發生什麼?你的'生物'是'Monoid'嗎? – Bergi

+0

我編輯了我的問題,並添加了一個開始和結束狀態的示例以及一些更多類型的說明。這是我生物的簡化版本,真實的東西不是幺半羣。如果列表是空的,我想我會期待回到原來的生物。 –

+1

我看到的問題是您提出的'applyChanges'函數不接受處於原始狀態 – Bergi

回答

4

State Creature Creature是這種計算的錯誤類型。正如你所看到的,你可以避開它,但是它不必要地使事情複雜化,因爲你實際上並不關心狀態變量!您只需使用它來存儲該函數的原始輸入...但是然後將其丟棄在applyChanges

A型,這將是更容易使用是Creature -> Creature,然後如果你有這樣的功能列表,以應用您只是想撰寫他們的所有,你可以用摺疊做的工作:

applyChanges :: [Creature -> Creature] -> Creature -> Creature 
applyChanges = foldr (.) id 
+1

我是新來的哈斯克爾,難以想象這將如何在實踐中發揮作用。如果我們有一個將狀態值加2的StatModifer和一個將此修飾符應用於所有統計值的函數,那麼實現將是什麼樣子? –

+2

@DanAmbrogio:如果我理解你的問題,你應該有'addMod :: StatModifier - > Stat a - > Stat a; addMod m(Stat ms a)= Stat(m:ms)a'向屬性添加一個修飾符,助手像'modAll :: StatModifier - > Creature - > Creature; modAll m c = c {strength = addMod m(strength c),...}',例如修改所有的統計數據。然後,你可以使'Creature - > Creature'功能像'enhanceAll = modAll(StatModifier Enhancement 2)'一樣將它們組合起來,或者用它們作爲'State'動作。 'foldr(。)id [f,g,h] x'與f(g(h(id x)))'相同:它從右向左應用每個函數。 –

+0

可能是值得的自己的SO問題。答案肯定會更具可讀性。 –