我需要一些Haskell的帮助。
我想读取一个字符串并将该字符串转换为布尔值列表的列表。
例如,"LLL\nbbb\nLLL"
应生成以下列表:[[True,True,True],[False,False,False],[True,True, True]]
。应该忽略任何其他事情。
我是函数式编程的新手。我尝试了以下方法:
StringParse :: String -> Matrix
StringParse s =
case s of
"L" -> Matrix [[True]]
"b" -> Matrix [[False]]
使用数据类型Matrix:
data Matrix = Matrix [[Bool]]
答案 0 :(得分:5)
您首先在子问题中拆分任务。
lines
。filter
的工作。L
转换为True
值,每个b
转换为False
。这只是map
操作。map
将它们应用于行列表。Matrix
数据构造函数中。在Haskell中将所有链接在一起非常容易:
parse :: String -> Matrix
parse = Matrix . map (map decide . filter isKnown) . lines
where decide 'L' = True
decide 'b' = False
isKnown 'L' = True
isKnown 'b' = True
isKnown _ = False
这将是一个非常好的解决方案。
实际上,在这里合并第二步和第三步可能更好:不是首先挑选我们可以处理的值,然后在单独的情况下处理相同的值集,我们可以同时做两个时间。 IMO最好的方式,虽然它现在可能让你困惑,但是使用列表是monad的事实:
parse' :: String -> Matrix
parse' = Matrix . map translate . lines
where translate line = do
ch <- line
case ch of 'L' -> [True]
'b' -> [False]
_ -> []
答案 1 :(得分:4)
让我们把它分解成小步骤。
您想将"LLL\nbbb\nLLL"
之类的字符串转换为Matrix [[True, True, True], [False, False, False], [True, True, True]]
。这意味着您希望将该字符串转换为[[True, True, True], [False, False, False], [True, True, True]]
,然后将其包装在Matrix
中。
这意味着您希望单独处理每一行,因此您需要将"LLL\nbbb\nLLL"
转换为["LLL", "bbb", "LLL"]
。很简单,Haskell有一个名为lines
的内置函数,它将为我们执行此操作,它会在换行符上拆分字符串。那么让我们写下目前为止的内容
parse :: String -> Matrix
parse s = Matrix $ {- something -} lines s
那么我们如何将一条线变成一个布尔列表呢?我们将每个单独的字符转换为布尔值,然后将该操作应用于每个字符。首先,我们应该编写一个辅助函数来匹配我们想要的字符
charToBool :: Char -> Bool
charToBool 'L' = True
charToBool 'b' = False
charToBool _ = False -- Catch-all. With this you don't actually need the 'b' case
请注意,这会将 Char 转换为Bool。现在我们可以将它映射到整行
lineToBools :: String -> [Bool]
lineToBools line = map charToBool line
现在,我们只需将此操作应用于我们拥有的所有行
parse s = Matrix $ map lineToBools $ lines s
你已经完成了!
有一种更短,更好的方法。首先,除非你真的需要它,不要在构造函数中包装[[Bool]]
,只需使用类型别名
type Matrix = [[Bool]]
接下来,可以在某种程度上内联这些功能
parse s = map (map charToBool) $ lines s
这可以将ETA缩减为
parse = map (map charToBool) . lines
但是,charToBool
也可以内联到(== 'L')
,因此您可以将整个内容写为
parse = map (map (== 'L')) . lines
我更喜欢它。
如果您想过滤掉意外的输入,您也可以
parse = map (map (== 'L')) . map (filter (`elem` "Lb")) . lines
并将其保存在一行中。
答案 2 :(得分:2)
parse :: String -> Matrix
parse = Matrix . map (map (=='L') . filter (\x -> x=='L' || x=='b')) . lines
应该做的诀窍:D
编辑:现在应该工作,感谢Tetigi和bheklilr!