【问题标题】:Haskell: Want a better way of doing: value == x || value == y ||Haskell:想要更好的做事方式:value == x ||值 == y ||
【发布时间】:2011-05-16 17:32:13
【问题描述】:

我是 Haskell 的新手,如果这非常明显,我很抱歉...


我制作了以下函数(此处用作询问多个value==something || value==somethingElse 检查的示例)来检查字符是否为数字:


isDigit :: Char -> Bool
isDigit x = 
    if 
    x == '0' 
    || x == '1'  
    || x == '2'  
    || x == '3'  
    || x == '4'  
    || x == '5'  
    || x == '6'  
    || x == '7'  
    || x == '8'  
    || x == '9'  
    then True  
    else False


当然,尽管必须有一种简洁的方法来编写像上面那样的函数,所以你不必重复|| x ==这么多?



提前感谢您的帮助:)

(如果相关:我使用 Hugs 作为解释器。)

【问题讨论】:

  • 由于您是 Haskell 的新手,从您的回答来看,我认为您应该阅读并了解 Haskell 中的模式匹配。
  • @Lagerbaer,什么?你是说守卫?这个问题没有很好地利用模式匹配。
  • 也许吧。但是他的第一个解决方案至少可以通过不使用 if ... then 而是使用模式匹配来做得更好。这表明他没有“默认”使用模式匹配,因此这是他应该学习的东西。
  • 大声笑,谢谢 Rei。我已经找到并阅读了大量的 learnyouahaskell.com,这绝对是我遇到的关于 Haskell 的最佳解释者。

标签: haskell idioms


【解决方案1】:

在这种情况下,您可以使用 Prelude 中的elem

isDigit x = elem x "0123456789"

(记住字符串是 Char 的列表)

或者你可以使用isDigit from Data.Char :-)

是的,有一种简洁的方法可以编写几乎所有重复的模式。这是如何为这个派生它的。从字符列表开始(为简洁起见,我只做 0-4)

"01234"

映射比较:

map (x ==) "01234"
  = [x == '0', x == '1', x == '2', x == '3', x == '4']
  = (x == '0') : (x == '1') : (x == '2') : (x == '3') : (x == '4') : []

然后使用foldrfoldr f z 最好被描述为一个函数,它接受一个列表并将 : 替换为 f[] 替换为 z

foldr (||) False (map (x ==) "01234")
  = x == '0' || x == '1' || x == '2' || x == '3' || x == '4' || False

你有它。 foldr 是列表函数的祖父,所以这是在没有显式递归的情况下实现它的“最低级别”方法。以下是您的词汇表的另外两个拼写:

isDigit x = any (x ==) "0123456789"
isDigit x = or [ x == d | d <- "0123456789" ]

如果我不得不猜测最常见的“惯用”拼写,那可能是第一个拼写的变体:

isDigit = (`elem` "0123456789")

一旦您熟悉了 Prelude 中的所有便捷功能,编写这样的代码就是一件轻而易举的事 :-)

【讨论】:

  • 谢谢。这是一个非常全面的答案,正是我想要的:)
  • 为了完整起见,在这种情况下,您还可以使用isDigit x = '0' &lt;= x &amp;&amp; x &lt;= '9'。不过一般来说,你当然需要`elem`
  • 如果检查的元素都是连续的,那么foo &lt;= x &amp;&amp; x &lt;= bar总是更好。
【解决方案2】:

另一个我没有看到的样式问题是函数

if expr then True else False

等价于简单

expr

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-17
    • 1970-01-01
    • 2016-02-26
    • 2016-07-17
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多