【发布时间】:2012-01-29 09:41:37
【问题描述】:
假设我有以下记录:
data Rec = Rec {
field1 :: Int,
field2 :: Int
}
函数怎么写:
changeField :: Rec -> String -> Int -> Rec
changeField rec fieldName value
这样我就可以将字符串“field1”或“field2”传入fieldName 参数并让它更新相关的字段?我知道 Data.Data 和 Data.Typeable 是在这里使用的,但我无法弄清楚这两个包。
我见过的一个库示例是 cmdArgs。下面是来自博客的excerpt,关于如何使用这个库:
{-# LANGUAGE DeriveDataTypeable #-}
import System.Console.CmdArgs
data Guess = Guess {min :: Int, max :: Int, limit :: Maybe Int} deriving (Data,Typeable,Show)
main = do
x <- cmdArgs $ Guess 1 100 Nothing
print x
现在我们有了一个简单的命令行解析器。一些示例交互是:
$ guess --min=10
NumberGuess {min = 10, max = 100, limit = Nothing}
【问题讨论】:
-
你可能不想这样做。你听说过lenses吗?我认为实现这一点的唯一方法是将字段名称与其参数索引配对并使用
gmapQi或类似的方法。 (您需要将deriving (Typeable, Data)添加到您的记录声明中才能有任何工作的希望;它不能用于任意类型。) -
我确实想这样做。我想创建一个库,用户可以在其中提供记录,并且该库可以通过解析一些文本来填充记录。文本将包含对我要设置的记录中的字段的引用。
-
示例选择不当,恐怕; cmdargs 的隐式模式因其杂质而成为最受诟病的 Haskell 库之一 :) 不过,如果您确实想要完成此操作,那么我仍然建议使用 Template Haskell 生成
recMap;它更灵活,更不神奇。 -
这种方式违背了 Haskell 编译时安全的心态。您应该考虑使用动态较少的解决方案
-
@Ana:当然可以,但是对这样一个问题的完整回答可能需要指出可能有更好的方法来实现相同的目标;如果有人问“我如何使用
unsafeCoerce在 Haskell 中的整数类型之间进行转换?”,请不要指出您应该使用fromIntegral来代替;因此我的cmets。