簡體   English   中英

Haskell構造函數類型模式匹配

[英]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.

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