首先,我是Haskell的新手,所以如果我问一些愚蠢的问题,请告诉我如何做得更好。谢谢:)
我的任务是获取符合特定条件的字符串列表。如果没有字符串符合要求,我想评估为Nothing
。所以我写了两个函数:
isSpecialLine :: String -> String -> Maybe Bool
isSpecialLine t s = Just $ (("[" ++ t ++ ":") `isPrefixOf` s) && ("]::" `isSuffixOf` s)
getLinesWith :: String -> String -> Maybe [String]
getLinesWith t = filterM (isSpecialLine t) . lines
此代码有效,但是我发现Maybe Bool
看起来有点奇怪。嘿,是二进制文件!它始终为True
或False
,因此isSpecialLine
的值将始终为Just True
或Just False
。就我而言,它永远不会Nothing
!
但是如果我将isSpecialLine
的输出类型更改为Bool
,则会出现以下问题:filterM
期望Maybe Bool
而不是Bool
。
好的,我这样做:
getLinesWith :: String -> String -> Maybe [String]
getLinesWith t = filterM (Just $ isSpecialLine t) . lines
现在,编译器抱怨类型不匹配:Maybe (String -> Bool)
与预期的String -> Maybe Bool
不匹配。好的,很合理。所以我:
getLinesWith :: String -> String -> Maybe [String]
getLinesWith t = Just $ filter (isSpecialLine t) . lines
再次键入不匹配项,这次的Maybe (String -> [String])
不是String -> Maybe [String]
。将[String]
封装为Maybe
monad的正确语法是什么?
答案 0 :(得分:6)
isSpecialLine
从不产生Nothing
,因此这很好地暗示了Maybe
也可能没有意义。
isSpecialLine :: String -> String -> Bool
isSpecialLine t s = (("[" ++ t ++ ":") `isPrefixOf` s) && ("]::" `isSuffixOf` s)
getLinesWith :: String -> String -> [String]
getLinesWith t = filter (isSpecialLine t) . lines
答案 1 :(得分:4)
在我看来,您这里不需要Array
(
[0] => Array
(
[letter] => A
[word] => Alpha
)
[1] => Array
(
[letter] => B
[word] => Bravo
)
[2] => Array
(
[letter] => C
[word] => Charlie
)
)
。您可以改为使用filter :: (a -> Bool) -> [a] -> [a]
:
filterM
实际上,这将返回isSpecialLine :: String -> String -> Bool
isSpecialLine t s = isPrefixOf ("[" ++ t ++ ":") s && isSuffixOf "]::" s
getLinesWith :: String -> String -> [String]
getLinesWith t = filter (isSpecialLine t) . lines
的列表,其中将保留与String
过滤器匹配的每个字符串。
答案 2 :(得分:1)
不是像这样使用Maybe
并从getLinesWith
解包数据,
getLinesWith :: String -> String -> Maybe [String]
...
getDate :: String -> String -> UTCTime
getDate t s =
timeFromString
. filter (/= ' ')
. getBetweenColons
. maybe ":01-01-1971:" head $ getLinesWith t s
在没有Maybe
的情况下,我获得了看起来更好(希望如此)的解决方案:
getLinesWith :: String -> String -> [String]
...
getDate :: String -> String -> UTCTime
getDate t s
| null date = timeFromString "01-01-1971"
| otherwise = timeFromString
. filter (/= ' ')
. getBetweenColons
. head $ date
where date = getLinesWith t s
实际上,当GHC抱怨Maybe
时,head []
周围的所有舞蹈都开始了。
谢谢大家的投入!