让我们把它分解成小步骤。
您想将字符串转换"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
这可以减少到
parse = map (map charToBool) . lines
但是,charToBool
也可以内联到(== 'L')
中,因此您可以将整个内容编写为
parse = map (map (== 'L')) . lines
我更喜欢。
如果你想过滤掉意外的输入,你也可以这样做
parse = map (map (== 'L')) . map (filter (`elem` "Lb")) . lines
并将其保留在一行中。