Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Haskell的替换中应用多个案例?_Haskell_Replace - Fatal编程技术网

如何在Haskell的替换中应用多个案例?

如何在Haskell的替换中应用多个案例?,haskell,replace,Haskell,Replace,我编写了一个函数,以便能够在Haskell中清除要处理的字号。它需要能够将-更改为空格(即45变为45)并删除其他非字母。我可以递归地定义它,但我真的想做一些更干净的事情 clean :: String -> String clean "" = "" clean ('-':cs) = ' ' : clean cs clean (c:cs) | isLetter c = c : clean cs | otherwise = clean cs 这导致我定义了一个自定义过

我编写了一个函数,以便能够在Haskell中清除要处理的字号。它需要能够将
-
更改为空格(即45变为45)并删除其他非字母。我可以递归地定义它,但我真的想做一些更干净的事情

clean :: String -> String
clean "" = ""
clean ('-':cs) = ' ' : clean cs
clean (c:cs)
    | isLetter c  = c : clean cs
    | otherwise   = clean cs
这导致我定义了一个自定义过滤器,并基于对的注释定义了替换自,因为我已经在使用Data.List.Split

clean :: String -> String
clean = filter (\c -> isLetter c || c == ' ') . replace "-" " " . filter (/= ' ')
  where
    replace :: String -> String -> String -> String
    replace old new = intercalate new . splitOn old

这个版本从整体上来说更混乱。此外,此版本不会删除原始字符串中的空格。是一种不同的约定或内置的东西,允许我使用干净的一行程序来实现这一点吗?

处理列表最强大的功能之一是(也称为
>=
)。您可以这样编写
clean
函数:

clean :: String -> String
clean = concatMap (\c -> if c == '-' then " " else [c | isLetter c])

这里有两件事:

  • 您需要删除所有不是字母或连字符的内容;及
  • 接下来我们用空格替换连字符
  • 因此,我们可以使用带有
    filter
    replace
    的管道来实现这一点:

      import Data.Bool(bool)
      import Data.Char(isLetter)
    
       map (\x -> bool ' ' x (x /= '-')) . filter (\x -> isLetter x || x == '-')
    -- \____________ __________________/   \______________ ____________________/
    --              v                                     v
    --             (2)                                   (1)
    
    我们可以使用列表理解来进行映射和筛选,如:

    import Data.Bool(bool)
    import Data.Char(isLetter)
    
    clean l = [bool ' ' x (x /= '-') | x <- l, isLetter x || x == '-']
    

    因此,如果
    x
    不是字母和连字符,我们将
    x
    的映射连接到
    ,如果
    x
    不是字母和连字符,则连接空字符串,或者连接到
    [x]
    (因此是一个单字符字符串)case
    x
    是一个字母。

    这是列表monad中
    do
    表示法的一个很好的用例

    clean :: String -> String
    clean string = do
      character <- string         -- For each character in the string...
      case character of
        '-'            -> " "     -- If it’s a dash, replace with a space.
        c | isLetter c -> pure c  -- If it’s a letter, return it.
        _              -> []      -- Otherwise, discard it.
    

    最后,请注意,
    isleter
    为所有Unicode字母返回true。如果您只关心ASCII,您可能希望使用
    isAscii c&&isleter c
    ,或
    isAsciiUpper c | | isAsciiLower c

    谢谢!我以前从未遇到过
    bool
    。看起来它基本上是一个if-else?@BrainFRZ:它是
    Bool
    的一个亚同构,但对于布尔型,它确实像
    if-then-else
    ,带有
    Bool
    clean :: String -> String
    clean string = do
      character <- string         -- For each character in the string...
      case character of
        '-'            -> " "     -- If it’s a dash, replace with a space.
        c | isLetter c -> pure c  -- If it’s a letter, return it.
        _              -> []      -- Otherwise, discard it.
    
    if
      | character == '-'   -> " "
      | isLetter character -> pure character
      | otherwise          -> []