[英]Haskell Constructor Type Pattern Matching
我在下面有一個簡單的類型和功能,但似乎有很多樣板,所以奇怪有更好的方法來做到這一點。 我猜的真正的問題是,如果我知道輸入是類型的能力,那么任何一個Str / Dex等,從中提取整數的最簡單方法是什么,沒有模式匹配它們中的每一個?
data Ability = StrAbi Integer
| DexAbi Integer
| ConAbi Integer
| IntAbi Integer
| WisAbi Integer
| ChaAbi Integer
deriving (Show)
data Modifier = Modifier Integer deriving (Show)
setModifier :: Ability -> (Ability, Modifier)
setModifier abi@(StrAbi s) = (abi, Modifier $ modifier' s)
setModifier abi@(DexAbi s) = (abi, Modifier $ modifier' s)
setModifier abi@(ConAbi s) = (abi, Modifier $ modifier' s)
setModifier abi@(IntAbi s) = (abi, Modifier $ modifier' s)
setModifier abi@(WisAbi s) = (abi, Modifier $ modifier' s)
setModifier abi@(ChaAbi s) = (abi, Modifier $ modifier' s)
謝謝, //
你能重構數據類型嗎?
data Ability = Ability { abilityType :: AbilityType, abilityValue :: Integer }
data AbilityType = Str | Dec | Con | Int | Wis | Cha
setModifier
與Willem Van Onsem的定義相同。
通常,如果您有一個數據結構,其中每個可能的構造函數都有一個具有相同語義含義的字段,您可以使用記錄語法 ,從而為該子項命名:
data Ability = StrAbi { abilityValue :: Integer }
| DexAbi { abilityValue :: Integer }
| ConAbi { abilityValue :: Integer }
| IntAbi { abilityValue :: Integer }
| WisAbi { abilityValue :: Integer }
| ChaAbi { abilityValue :: Integer }
deriving (Show)
好的是,你自動構建了一個函數abilityValue :: Ability -> Integer
,因此可以訪問該字段。
接下來我們可以簡單地寫:
setModifier :: Ability -> (Ability, Modifier)
setModifier abi = (abi, Modifier $ modifier' $ abilityValue abi)
當然有一些努力來指定字段的名稱,但如果這些值具有“類似的語義含義”,那么它通常會得到回報,因為你已經引入了“getter”(並且你可以使用記錄符號來表示“setter” “)。
回答關於使用Lens的評論問題(在這個答案中使用MicroLens平台,但對於這些操作,其代碼與具有較小依賴性的完整Lens完全相同):
{-# LANGUAGE TemplateHaskell #-}
import Lens.Micro.Platform
data Ability
= StrAbi { _abilityValue :: Integer }
| DexAbi { _abilityValue :: Integer }
| ConAbi { _abilityValue :: Integer }
| IntAbi { _abilityValue :: Integer }
| WisAbi { _abilityValue :: Integer }
| ChaAbi { _abilityValue :: Integer }
deriving (Show)
makeLenses ''Ability
-- Just some examples
getAbilityValue :: Ability -> Integer
getAbilityValue ab = ab ^. abilityValue
setAbilityValue :: Ability -> Integer -> Ability
setAbilityValue ab val = ab & abilityValue .~ val
modifyAbilityValue :: Ability -> (Integer -> Integer) -> Ability
modifyAbilityValue ab f = ab & abilityValue %~ f
-- Edit after reading the question instead of just the comment:
data Modifier = Modifier Integer deriving (Show)
setModifier :: Ability -> (Ability, Modifier)
setModifier ab = (ab,Modifier (ab ^. abilityValue))
-- or import Control.Arrow and
-- setModifier = id &&& Modifier . (^. abilityValue)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.