我有一种数据类型可以跟踪状态。让我们说它看起来像这样:
data State = State String String Int
多个函数使用State
并返回一个新函数。例如:
convert :: State -> Int -> State
convert (State a b c) 0 = State "new" b c
convert (State a b c) 1 = State a "new" c
convert (State a b c) 2 = State a b 0
(1)当我编辑State
数据类型(例如,为了保存额外的Int
)时,我需要编辑所有函数中的模式匹配。在这种情况下使用记录语法会更好吗?
data State = State { a :: String, b :: String, c :: Int }
convert :: State -> Int -> State
convert state 0 = State "new" (b state) (c state)
convert state 1 = State (a state) "new" (c state)
convert state 2 = State (a state) (b state) 0
现在,我不必在更改数据类型State
时编辑模式匹配。然而,右侧的建设性呼叫遇到了同样的问题。有没有解决的办法?我可以定义一些函数来创建State
s(只有那些需要在State
构造函数更改时才被操作)。
(2)我猜还有其他方法可以解决这个问题......
答案 0 :(得分:4)
您可以使用记录更新语法:
convert state 0 = state { a = "new" }
convert state 1 = state { b = "new" }
convert state 2 = state { c = 0 }
或者你可以使用镜头(特别是爱德华的lens库):
{-# LANGUAGE: TemplateHaskell #-}
import Control.Lens
data State = State
{ _a :: String
, _b :: String
, _c :: Int
} deriving (Eq, Show, Read)
makeLenses ''State
convert :: Int -> State -> State
convert 0 = set a "new"
convert 1 = set b "new"
convert 2 = set c 0
-- Or using the infix version of set
-- convert 0 = a .~ "new"
-- convert 1 = b .~ "new"
-- convert 2 = c .~ 0
如果你想进一步了解镜头库中出现的黑魔法,那里有很多教程,文档一般都很好,但这不属于这个问题的范围