gpt4 book ai didi

haskell - 将命令行参数派生的真值表转换为数据类型

转载 作者:行者123 更新时间:2023-12-03 23:39:53 25 4
gpt4 key购买 nike

我的问题源于真实世界的代码比下面的例子(由几个模拟函数组成)复杂得多。这个例子应该说明我的问题产生的现象:(或者)case/of 语句中的一个巨大的表(或者嵌套的巨大级联 ifs)。 case/of 语句包含类似于真值表的内容,它决定如何参数化结果记录的类型(称为 ComposedRecord 因为它是三个通用类型记录的组合)。模拟函数已经实现,但我对巨大的 case/of block 不满意。因此,我试图找到一个更简洁的解决方案:

-- intermediate record type 1
data SimpleRecord = SimpleRecord {
_description :: String
}

-- intermediate record type 2
data DetailedRecord = DetailedRecord {
_title :: String,
_details :: String
}

-- intermediate record type 3
data RawRecord = RawRecord {
_x :: Int,
_y :: Int,
_z :: Int
}

class AnyRecord r where
instance AnyRecord SimpleRecord
instance AnyRecord DetailedRecord
instance AnyRecord RawRecord

-- to-be-serialized record type (composed of intermediate record types 1, 2 or 3)
data ComposedRecord a b c = ComposedRecord {
_a :: a,
_b :: b,
_c :: c
}

inputToSimpleRecord :: String -> SimpleRecord
inputToSimpleRecord input = SimpleRecord {
_description = "description derived from input"
}

inputToDetailedRecord :: String -> DetailedRecord
inputToDetailedRecord input = DetailedRecord {
_title = "title derived from input",
_details = "details derived from input"
}

inputToRawRecord :: String -> RawRecord
inputToRawRecord input = RawRecord {
_x = 1, -- number derived from input string
_y = 2, -- number derived from input string
_z = 3 -- number derived from input string
}

serializeToJsonString :: (AnyRecord a, AnyRecord b, AnyRecord c) => ComposedRecord a b c -> String
serializeToJsonString composedRecord = "{}"
-- this function will also contain some post processing of the records
-- thus the "AnyRecord" type constraint is needed

commandLineArguments = ["simple", "detailed", "raw"]
-- the value of commandLineArguments will be read from the command line

inputFromCommandLine = "1, 2, 3" -- some input

main = do
let result = case commandLineArguments of
["simple", "simple", "simple"] -> serializeToJsonString ComposedRecord {
_a = inputToSimpleRecord inputFromCommandLine,
_b = inputToSimpleRecord inputFromCommandLine,
_c = inputToSimpleRecord inputFromCommandLine
}
["simple", "simple", "detailed"] -> serializeToJsonString ComposedRecord {
_a = inputToSimpleRecord inputFromCommandLine,
_b = inputToSimpleRecord inputFromCommandLine,
_c = inputToDetailedRecord inputFromCommandLine
}
["simple", "simple", "raw"] -> serializeToJsonString ComposedRecord {
_a = inputToSimpleRecord inputFromCommandLine,
_b = inputToSimpleRecord inputFromCommandLine,
_c = inputToRawRecord inputFromCommandLine
}
["simple", "detailed", "simple"] -> serializeToJsonString ComposedRecord {
_a = inputToSimpleRecord inputFromCommandLine,
_b = inputToDetailedRecord inputFromCommandLine,
_c = inputToSimpleRecord inputFromCommandLine
}
["simple", "detailed", "detailed"] -> serializeToJsonString ComposedRecord {
_a = inputToSimpleRecord inputFromCommandLine,
_b = inputToDetailedRecord inputFromCommandLine,
_c = inputToDetailedRecord inputFromCommandLine
}
["simple", "detailed", "raw"] -> serializeToJsonString ComposedRecord {
_a = inputToSimpleRecord inputFromCommandLine,
_b = inputToDetailedRecord inputFromCommandLine,
_c = inputToRawRecord inputFromCommandLine
}
["simple", "raw", "raw"] -> serializeToJsonString ComposedRecord {
_a = inputToSimpleRecord inputFromCommandLine,
_b = inputToRawRecord inputFromCommandLine,
_c = inputToRawRecord inputFromCommandLine
}
["detailed", "simple", "simple"] -> serializeToJsonString ComposedRecord {
_a = inputToDetailedRecord inputFromCommandLine,
_b = inputToSimpleRecord inputFromCommandLine,
_c = inputToSimpleRecord inputFromCommandLine
}
-- and so on...

putStrLn result

最佳答案

对我来说,这里的关键元素是 serializeToJsonString 的类型。该函数不明确需要Record,只要它是AnyRecord。考虑到这一点,您可以使用 ExistentialQuantification 来封装该想法。请考虑以下事项:

data AnyRecordData = forall r. AnyRecord r => AnyRecordData r

data ComposedRecord = ComposedRecord {
_a :: AnyRecordData,
_b :: AnyRecordData,
_c :: AnyRecordData
}


inputToAnyRecord :: String -> String -> AnyRecordData
inputToAnyRecord "simple" = AnyRecordData . inputToSimpleRecord
inputToAnyRecord "detailed" = AnyRecordData . inputToDetailedRecord
inputToAnyRecord "raw" = AnyRecordData . inputToRawRecord

main = do
let result = case commandLineArguments of
[a,b,c] -> serializeToJsonString ComposedRecord {
_a = inputToAnyRecord a inputFromCommandLine
, _b = inputToAnyRecord b inputFromCommandLine
, _c = inputToAnyRecord c inputFromCommandLine
}

putStrLn result

关于haskell - 将命令行参数派生的真值表转换为数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66517219/

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