【问题标题】:remove zero from infinite float list从无限浮动列表中删除零
【发布时间】:2016-02-16 06:07:46
【问题描述】:

我想从无限的浮动列表中进行采样以供 QuickCheck 使用。但是,由于我打算使用除法,我想从该列表中删除 zero。这是一个概念上很简单的问题,我想知道我是否可以通过列表理解来做到这一点,如果不能,在 Haskell 中实现这一目标的最简单方法是什么?

[x | x <- floats, x /= 0] -- this seems reasonable, but where do I get floats from?

我目前的解决方法(糟糕):

import Test.QuickTest

divGen :: Gen (Maybe Float)
divGen = do
    x <- arbitrary
    if x /= 0
    then return $ Just x
    else return Nothing

【问题讨论】:

  • "我从哪里得到floats?"真是个问题;我看不出可以从给出的信息中得到答案。你想在那个列表中出现什么......?
  • @DanielWagner,检查我的编辑。该解决方法有效,并为我提供了我期望的值。
  • 看来您的实际问题是如何生成一个无限的随机浮点数列表?问题中的列表理解非常适合从无限的浮点数列表中过滤零元素。

标签: haskell list-comprehension quickcheck


【解决方案1】:

您可以使用 QuickCheck 的 suchThat 组合子生成满足给定谓词的 arbitrary 值:

divisor :: Gen Float
divisor = arbitrary `suchThat` (/= 0)

示例用法:

my_prop x = forAll divisor $ \d -> (x / d) * d =~= x

【讨论】:

  • 这是您和@Zeta 的答案之间的艰难选择。两者都提高了我对 QuickCheck 的了解。谢谢!
  • =~= 运算符从何而来?
  • =~= 这里是一个足够不精确的比较器(因为比较Doubles 不是一个好主意)。参见例如hackage.haskell.org/package/elynx-tools-0.5.0/docs/…
【解决方案2】:

这已经在 QuickCheck 中,即NonZero。您的无限浮动列表可以建模为

nonZeroFloat :: Gen Float
nonZeroFloat = fmap getNonZero arbitrary

-- You probably want to use a shorter name:
infiniteListOfNonZeroFloats :: Gen [Float]
infiniteListOfNonZeroFloats = infiniteListOf nonZeroFloat

之后,您可以使用forAll

prop_something = forAll infiniteListOfNonZeroFloats $ \xs -> ...
-- or
prop_something = forAll (infinitelistOf $ getNonZero `fmap` arbitrary) $ \xs ->
                    ...

请注意,NonZero 的使用通过模式匹配要顺畅得多:

prop_nonzero :: NonZero Float -> ...
prop_nonzero (NonZero x) = ...

【讨论】:

    【解决方案3】:

    因此,如果您只想从列表中删除零,则可以执行以下操作:

    1. 函数定义:

      withoutZeros:: (Eq a,Num a)->[a]->[a] 
      
    2. 此代码将删除所有零。您只需更改 (/=) 内的条件即可删除任何数字。

      withoutZeros =filter (/=0)  
      

    我在函数定义中使用了(Eq a,Num a),因为比较需要Eq a-&gt;(即(/=))和Num a-&gt;。这将允许您在 Integer 和 Float 列表中使用此函数。

    【讨论】:

    • 欢迎来到 Stackoverflow!你知道你可以在你的答案中使用 Markdown 风格的格式并在发布之前预览它们吗?我已对您的答案进行了修改以使其更具可读性,但我对 Haskell 不是很熟悉,因此请随时修复我可能不小心引入的任何错误。
    【解决方案4】:

    我可以用列表理解来做吗?

    当然,这种理解对我来说很好。

    我从哪里获得floats

    取决于你想成为什么样的人。

    对于您的生成器代码,我要说的唯一评论是拒绝采样是常用技巧:

    divGen = do
        x <- arbitrary
        if x /= 0 then return x else divGen
    

    【讨论】:

    • 这对你有用吗?我之前试过,sample divGen给了我一个无限循环。
    • arbitrary 是无限循环还是总是返回 0?
    • @ThomasM.DuBuisson,我在Interactive-Haskell (Emacs) 中运行它,它只是挂起,直到我打断它。没有返回值。
    • 你想要arbitrary `suchThat` (/= 0)
    猜你喜欢
    • 2021-11-02
    • 2021-01-24
    • 2018-11-15
    • 1970-01-01
    • 2018-01-14
    • 2019-12-09
    • 2014-04-01
    • 1970-01-01
    • 2015-11-11
    相关资源
    最近更新 更多