如果我有数据类型:
data Component = PositionC Double Double | HealthC Double | NameC String
Run Code Online (Sandbox Code Playgroud)
Components 的集合我可以使用什么技术,数据结构,TemplateHaskell功能来满足上述标准?
我已经尝试过Data.Set和Data.Map但没有成功.
Data.Map尝试:
import Data.Map
data Component = PositionC Double Double | HealthC Double | NameC String
-- Unacceptable code duplication
data ComponentType = PositionCT | HealthCT | NameCT
deriving (Eq, Ord)
type ComponentMap = Map ComponentType Component
foo :: ComponentMap
-- More annoying code duplication
foo = fromList [(HealthCT, HealthC 100), (NameCT, NameC "John")]
fooHealth = foo ! HealthCT -- However, accessing works great
Run Code Online (Sandbox Code Playgroud)
Data.Set尝试:
import Data.Set (Set)
import qualified Data.Set as Set
data Component = PositionC Double Double | HealthC Double | NameC String
deriving Eq
foo :: Set Component
foo = Set.fromAscList [HealthC 100, NameC "John"] -- This works well
-- But accessing elements is very bad
fooHealth = Set.elemAt 0 $ Set.filter p foo
where p (HealthC _) = True
p _ = False
Run Code Online (Sandbox Code Playgroud)
一个选项是使用带有可选字段的记录:
data Component = Component
{ positionC :: Maybe (Double, Double)
; healthC :: Maybe Double
; nameC :: Maybe String
}
Run Code Online (Sandbox Code Playgroud)
直观地说,访问字段也比使用Set或更便宜Map.
设置字段
moveToOrigin c = c { positionC = Just (0,0) }
Run Code Online (Sandbox Code Playgroud)
得到一个领域
-- Requires health to be present
isDead c = fromJust (healthC c) == 0
-- If health is unknown returns False
saferIsDead c = health C == Just 0
Run Code Online (Sandbox Code Playgroud)