如何使它更好? “也许布尔”看起来不太好

时间:2019-10-07 14:10:29

标签: haskell monads maybe

首先,我是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看起来有点奇怪。嘿,是二进制文件!它始终为TrueFalse,因此isSpecialLine的值将始终为Just TrueJust 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的正确语法是什么?

3 个答案:

答案 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 []周围的所有舞蹈都开始了。 谢谢大家的投入!