【问题标题】:What does % do in Haskell?% 在 Haskell 中做了什么?
【发布时间】:2019-07-12 10:22:49
【问题描述】:

我习惯于在其他语言中使用 % 来表示“模”。在 Haskell 中,我们必须使用 mod x yx `mod` y。那么,这个符号在 Haskell 中是用来做什么的呢?

【问题讨论】:

  • 显示其使用示例。我不记得它的任何用途,但很有可能自己定义它,所以库可以定义它。
  • 它在Data.Ratio,见这里:hackage.haskell.org/package/base-4.12.0.0/docs/…(当然,除非在另一个库中有%的另一个定义,这是完全可能的。)

标签: haskell modulo


【解决方案1】:

在“Old School” Davies Introduction to Functional Programming Systems Using Haskell中找到了这个。 (他经常将 Haskell 与 Pascal 进行比较。)这​​是对堆栈算法的模拟

type Stack = [Float]

push :: Float -> Stack -> Stack
push x stack = x : stack

addStack :: Stack -> Stack
addStack (x:y:stack) = (y + x) : stack

subtStack :: Stack -> Stack
subtStack (x:y:stack) = (y - x) : stack

multStack :: Stack -> Stack
multStack  (x:y:stack) = (y * x) : stack

divStack :: Stack -> Stack
divStack  (x:y:stack) = (y / x) : stack

emptyStack :: Stack
emptyStack = []

popStack :: Stack -> (Float, Stack)
popStack (top:rest) = (top,rest)

然后

let f % g     = g . f
    actionsOn = push 12.2 %
                push 7.1 %
                push 6.7 %
                divStack %
                push 4.3 %
                subtStack %
                multStack %
                push 2.2 %
                addStack
in popStack (actionsOn emptyStack)

(-37.331642,[])

这只是一个看起来很疯狂的嵌套函数的简洁版本

popStack (addStack (push 2.2 (multStack (subtStack (push 4.3 (divStack (push 6.7 (push 7.1 (push 12.2 emptyStack)))))))))

它本身避免为每个堆栈操作创建和传递一个新堆栈。总而言之,YAMAMOTO Yuji 一开始所说的在这里适用,而不是任何Ratio AFAIK 的东西。

【讨论】:

    【解决方案2】:

    快速查看Hoogle,您可以看到% 是一个定义为的中缀函数

    (%) :: Integral a => a -> a -> Ratio a
    

    你可以猜到它是Data.Ratio 库的一部分,主要处理比率(即:分数)。它是代码

    x % y = reduce (x * signum y) (abs y)
    

    因此给定两个积分 (x,y) ,它返回一个不可约分数 x/y

    【讨论】:

    • 从未听说过 Hoogle。我是 Haskell 的新手。我通过 DDGo 搜索,没有一篇文章提到 Data.Ratio。此资源未包含在一般搜索结果中。见:duckduckgo.com/…
    • 有没有办法在 GHCi/Prelude 中查找 Data.Ratio 的那些类型定义?我已经尝试:t % 无济于事
    • @Ryan,haskell.org/hoogle 的 Hoogle 是 Haskell 库的搜索引擎。您可以通过该链接访问它,然后您可以搜索任何功能、一些功能描述和——最重要的——功能类型。正如我所说,%Data.Ratio 库的一部分,所以在你可以在GHCi 中使用它之前——包括:t,你需要通过import Data.Ratio 导入它。然后你可以看到类型。还请记住,您可以使用:info,它有时会为您提供更多信息,而不仅仅是:t
    【解决方案3】:

    在 Haskell 中,我们可以像普通函数一样使用各种符号(包括%)定义二元运算符,因此您可以将% 定义为您想要的任意运算符(在您定义它的模块中)。

    作为最典型的情况,%Data.Ratio module 提供为Ratio 类型的构造函数。

    在 GHCi 上尝试以下代码以确保 %Data.Ratio 提供:

    ghci> 3 % 9
    
    <interactive>:1:3: error:
        Variable not in scope: (%) :: Integer -> Integer -> t
    ghci> import Data.Ratio
    ghci> 3 % 9
    1 % 3
    

    请记住,您可以在这些搜索引擎中搜索此类运算符和函数:

    其实我查过%是如何被Hoogle定义的。

    % 是一个中缀函数,定义为

    (%) :: Integral a => a -> a -> Ratio a
    

    从上面的类型定义中,您可以看到它是Data.Ratio 库的一部分,主要处理比率(即:分数)。它的代码是

    x % y = reduce (x * signum y) (abs y)
    

    因此给定两个积分 (x,y) ,它返回一个不可约分数 x/y

    【讨论】:

      【解决方案4】:

      Data.Ratio 使用% 作为构造函数,但除非该类型是在Integral 类型类之前定义的,否则它不能解释为什么% 可以供@ 使用987654327@。 (当然,合格的导入允许您在多个模块中使用相同的运算符名称,因此无论哪种方式,Data.Ratio 使用% 都不是真正的原因。)

      但是请注意,Integral 定义了 both mod and rem functions。我怀疑% 被故意排除在Integral 之外,都是为了避免1)选择它是否应该是modrem 的别名,以及2)让人们记住哪个选择制作完成。

      另外,languages use different definitions for %,所以(%) = mod(%) = rem 都有可能让某人感到困惑。

      【讨论】:

      • 还有一个不错的版本(我想可能是在 Python 中?),无论操作数的符号如何,都能保证得到肯定的结果,并保证 q * n + r = m
      • Python % 是 Haskell mod,我相信。
      • 嗯。搞错了R6RS Scheme 的mod 使用“欧几里得风格”,PureScript 也是如此(它曾经使用 Knuth 风格,但已切换)。
      【解决方案5】:

      Searching for (%) on Stackage Hoogle,看来Data.Ratio% 运算符定义为从分子和分母构造Ratio 值。一个 GHCi 示例:

      Prelude> :m + Data.Ratio
      Prelude Data.Ratio> let x = 1 % 2
      Prelude Data.Ratio> x
      1 % 2
      Prelude Data.Ratio> :t x
      x :: Integral a => Ratio a
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        • 2022-10-08
        • 1970-01-01
        • 2014-08-03
        相关资源
        最近更新 更多