编辑数据类型的构造函数时,最小化代码更改

时间:2014-05-27 20:37:56

标签: haskell

我有一种数据类型可以跟踪状态。让我们说它看起来像这样:

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)我猜还有其他方法可以解决这个问题......

1 个答案:

答案 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

如果你想进一步了解镜头库中出现的黑魔法,那里有很多教程,文档一般都很好,但这不属于这个问题的范围