gpt4 book ai didi

haskell - 以记录字段名称作为变量的模板 Haskell?

转载 作者:行者123 更新时间:2023-12-04 03:45:48 25 4
gpt4 key购买 nike

我有以下实现 monad 的代码。我正在尝试使用它来简化稍后具有更复杂逻辑的字段设置。

data Rec = Rec {
alpha :: Int,
beta :: Double,
} deriving (Show)
defaultRec = Rec 0 0 0

data Record r = Record { runRecord :: Rec -> (Rec, r) }
instance Monad Record where
return r = Record $ \s -> (s, r)
a >>= b = Record $ \s -> let (q, r) = runRecord a s in runRecord (b r) q

createRecord f = fst $ runRecord f defaultRec

changeAlpha x = Record $ \s -> (s { alpha = x }, ())

我会使用这样的代码:
myRecord = createRecord (changeAlpha 9)

此代码有效,但我想使用 Template Haskell 来简化 changeAlpha 函数。有这样的东西会很棒:
changeBeta x = $(makeChange beta) x

现在,我已经做到了:
changeBeta x = Record $ $([| \z -> \s -> (s { beta = z }, ()) |]) x

但是,一旦我将其更改为:
changeBeta f x = Record $ $([| \z -> \s -> (s { f = z }, ()) |]) x

我明白了:
TestTH.hs:21:49: `f' is not a (visible) constructor field name

没有变化工作。这可能吗?

最佳答案

问题是您只能拼接类型、表达式或声明列表。记录字段标签两者都不是,因此您必须使用 TH 组合子来制作 Q Exp 类型的表达式。然后将其拼接起来,尽管您仍然可以对其余部分使用牛津括号:

makeChange :: Name -> Q Exp
makeChange x = [|
\z -> Record $ \s -> ( $(recUpdE [| s |] [fieldExp x [| z |]]), () ) |]

要使用它,您必须引用要更改的字段的名称:
changeBeta :: Double -> Record ()
changeBeta x = $(makeChange 'beta) x

关于haskell - 以记录字段名称作为变量的模板 Haskell?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8469044/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com