我有一个字符串列表:
[" ix = index"," ctr = counter"," tbl = table"]
Run Code Online (Sandbox Code Playgroud)
我想从它创建一个元组,如:
[("ix","index"),("ctr","counter"),("tbl","table")]
Run Code Online (Sandbox Code Playgroud)
我甚至尝试过:
genTuple [] = []
genTuples (a:as)= do
i<-splitOn '=' a
genTuples as
return i
Run Code Online (Sandbox Code Playgroud)
任何帮助都会受到赞赏谢谢.
Haskell的类型系统非常具有表现力,因此我建议从类型方面考虑问题.这样做的好处是你可以"自上而下"解决问题,并且可以随时对整个程序进行类型检查,这样你就可以及早发现各种错误.一般方法是逐步将问题划分为较小的函数,每个函数undefined最初都保留,但具有一些合理的类型.
你想要的是一个函数(让我们称它convert),它取一个字符串列表并生成一个元组列表,即
convert :: [String] -> [(String, String)]
convert = undefined
Run Code Online (Sandbox Code Playgroud)
很明显,输入列表中的每个字符串都需要解析为2元组的字符串.但是,解析可能会失败 - 纯粹的类型String无法保证输入字符串格式正确.所以你的parse函数可能会返回一个元组.我们得到:
parse :: String -> Maybe (String, String)
parse = undefined
Run Code Online (Sandbox Code Playgroud)
我们可以convert使用mapMaybe以下方法立即将其插入我们的函
convert :: [String] -> [(String, String)]
convert list = mapMaybe parse list
Run Code Online (Sandbox Code Playgroud)
到目前为止,这么好 - 但parse实际上还是如此undefined.假设它应该首先验证输入字符串是否为"有效",如果是,则将其拆分.所以我们需要
valid :: String -> Bool
valid = undefined
split :: String -> (String, String)
split = undefined
Run Code Online (Sandbox Code Playgroud)
现在我们可以定义parse:
parse :: String -> Maybe (String, String)
parse s | valid s = Just (split s)
| otherwise = Nothing
Run Code Online (Sandbox Code Playgroud)
是什么让一个字符串valid?让我们说它必须包含一个=标志:
valid :: String -> Bool
valid s = '=' `elem` s
Run Code Online (Sandbox Code Playgroud)
对于拆分,我们将所有字符都放在第=一个元组元素的第一个元素中,其余字符用于第二个元素元素.但是,您可能还想修剪前导/尾随空格,因此我们需要另一个函数.现在,让我们做一个无操作
trim :: String -> String
trim = id
Run Code Online (Sandbox Code Playgroud)
使用这个,我们可以最终定义
split :: String -> (String, String)
split s = (trim a, trim (tail b))
where
(a, b) = span (/= '=') s
Run Code Online (Sandbox Code Playgroud)
请注意,我们可以安全地tail在这里调用,因为我们知道它b永远不会是空的,因为它总是有一个分隔符(这是valid经过验证的).类型方面,使用"非空字符串"表达此保证会很好,但可能有点过度设计.:-)
现在,这个问题有很多解决方案,这只是一个例子(并且有一些方法可以使用eta缩减或现有库来缩短代码).我试图解决的主要问题是Haskell的类型系统允许您以类型为导向的方式处理问题,这意味着编译器可以帮助您从一开始就充实解决方案.