首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Haskell中的替换中应用多个案例?

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

Stack Overflow用户
提问于 2017-11-04 19:17:03
回答 3查看 770关注 0票数 3

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

代码语言:javascript
复制
clean :: String -> String
clean "" = ""
clean ('-':cs) = ' ' : clean cs
clean (c:cs)
    | isLetter c  = c : clean cs
    | otherwise   = clean cs

这导致我定义了一个自定义过滤器,并根据对Data.List.Split的注释定义了来自这个答案的替换,因为我已经在使用Data.List.Split了。

代码语言:javascript
复制
clean :: String -> String
clean = filter (\c -> isLetter c || c == ' ') . replace "-" " " . filter (/= ' ')
  where
    replace :: String -> String -> String -> String
    replace old new = intercalate new . splitOn old

这个版本作为一个整体甚至更加混乱。此外,此版本不会删除原始字符串中的空格。一个不同的惯例或内置的东西可以让我用一个干净的衬里来完成这个任务吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-11-04 19:38:13

处理列表的最强大功能之一是concatMap (a.k.a )。>>=)。您可以编写如下clean函数:

代码语言:javascript
复制
clean :: String -> String
clean = concatMap (\c -> if c == '-' then " " else [c | isLetter c])
票数 7
EN

Stack Overflow用户

发布于 2017-11-04 19:47:43

这里有两件事:

  1. 你需要删除所有不是字母或连字符的东西;以及
  2. 接下来,我们用空格替换连字符。

因此,我们可以使用filterreplace的管道来完成这一任务。

代码语言:javascript
复制
  import Data.Bool(bool)
  import Data.Char(isLetter)

   map (\x -> bool ' ' x (x /= '-')) . filter (\x -> isLetter x || x == '-')
-- \____________ __________________/   \______________ ____________________/
--              v                                     v
--             (2)                                   (1)

我们可以使用列表理解来进行映射和筛选,例如:

代码语言:javascript
复制
import Data.Bool(bool)
import Data.Char(isLetter)

clean l = [bool ' ' x (x /= '-') | x <- l, isLetter x || x == '-']

我们还可以使用单个函数,例如执行一个concatMap

代码语言:javascript
复制
import Data.Bool(bool)
import Data.Char(isLetter)

concatMap (\x -> bool (bool "" " " (x == '-')) [x] (isLetter x))

因此,在这里,我们将x""的映射连接起来,以防x不是字母和连字符,或者空字符串(如果不是字母或连字符),或者[x] (所以是1字符字符串),以防x是字母。

票数 4
EN

Stack Overflow用户

发布于 2017-11-05 11:13:50

对于列表中的do符号来说,这是一个非常好的用例。

代码语言:javascript
复制
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.

这最终是concatMap的简单语法糖。如果您愿意,pure c也可以编写为[c];更重要的是," "可以编写为pure ' '[' ']。作为另一种选择,您可能会发现使用MultiWayIf扩展可以更容易阅读:

代码语言:javascript
复制
if
  | character == '-'   -> " "
  | isLetter character -> pure character
  | otherwise          -> []

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47114615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档