简体   繁体   English

% 在 Haskell 中做什么?

[英]What does % do in Haskell?

I'm used to using % to mean "modulo" in other languages.我习惯于使用 % 来表示其他语言中的“模”。 In Haskell, we have to use mod xy or x `mod` y .在 Haskell 中,我们必须使用mod xyx `mod` y So, what is this symbol used for in Haskell?那么,这个符号在 Haskell 中是做什么用的呢?

With a quick look on Hoogle , you can see that % is an infix function defined as快速浏览一下Hoogle ,您可以看到%是一个定义为的中缀函数

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

and as you can guess it is part of the Data.Ratio library, which mostly deals with ratios (ie: fractions).你可以猜到它是Data.Ratio库的一部分,主要处理比率(即:分数)。 It is code is它的代码是

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

thus given two integrals (x,y) , it returns an irreducible fraction x/y因此给定两个积分 (x,y) ,它返回一个不可约分数 x/y

In Haskell, we can define binary operators with various symbols (including % ) like ordinary functions, So you can define % as an arbitrary operator you want (in the module which you define it).在 Haskell 中,我们可以像普通函数一样定义带有各种符号(包括% )的二元运算符,因此您可以将%定义为您想要的任意运算符(在您定义它的模块中)。

As the most typical case, % is provided as the constructor of the Ratio type by Data.Ratio module .作为最典型的情况, %Data.Ratio 模块提供为Ratio类型的构造函数。

Try the code below on GHCi to make sure that % is provided by Data.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

And remember you can search such operators and functions in these search engines:请记住,您可以在这些搜索引擎中搜索此类运算符和函数:

Actually I've looked up how % is defined by Hoogle .实际上,我已经查过 Hoogle是如何定义%

% is an infix function defined as % 是一个中缀函数,定义为

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

and from the type definition above, you can see that it is part of the Data.Ratio library, which mostly deals with ratios (ie: fractions).并且从上面的类型定义可以看出它是Data.Ratio库的一部分,主要处理比率(即:分数)。 Its code is它的代码是

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

thus given two integrals (x,y) , it returns an irreducible fraction x/y因此给定两个积分 (x,y) ,它返回一个不可约分数 x/y

Searching for (%) on Stackage Hoogle , it appears that Data.Ratio defines the % operator as constructing a Ratio value from a numerator and denominator.在 Stackage Hoogle 上搜索(%) ,似乎Data.Ratio%运算符定义为根据分子和分母构造Ratio值。 A GHCi example:一个 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

Data.Ratio uses % as a constructor, but unless that type was defined before the Integral type class, it doesn't explain why % was available for use by Data.Ratio . Data.Ratio使用%作为构造函数,但除非该类型是在Integral类型类之前定义的,否则它无法解释为什么%可供Data.Ratio使用。 (Of course, qualified imports allow you to use the same operator name in multiple modules, so either way, % being used by Data.Ratio isn't really a reason.) (当然,限定导入允许您在多个模块中使用相同的运算符名称,因此无论哪种方式, Data.Ratio使用% Data.Ratio是真正的原因。)

Note, however, that Integral defines both mod and rem functions .但是请注意, Integral定义modrem函数 I suspect that % was intentionally left out of Integral , both to avoid 1) making a choice as to whether it should be an alias for mod or rem , as well as 2) making people remember which choice was made.我怀疑%被故意排除在Integral ,以避免 1) 选择它是否应该是modrem的别名,以及 2) 让人们记住做出了哪个选择。

Also, languages use different definitions for % , so either (%) = mod or (%) = rem had the potential for confusing someone .此外, 语言对%使用不同的定义,因此(%) = mod(%) = rem都有可能混淆某人

Found this in "Old School" Davies Introduction to Functional Programming Systems Using Haskell .在“老派”戴维斯介绍使用 Haskell 的函数式编程系统中找到了这个。 (He constantly compares Haskell to Pascal.) It's a simulation of stack arithmetic (他经常将 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)

Then然后

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,[])

This is just a neater version of a crazy-looking nested function这只是一个看起来很疯狂的嵌套函数的更简洁版本

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

which itself avoids creating and passing a new stack for each stack operation.它本身避免为每个堆栈操作创建和传递一个新堆栈。 In summary, what YAMAMOTO Yuji says right at the beginning is applicable here and not really any Ratio stuff AFAIK.总之,YAMAMOTO Yuji 一开始所说的适用于这里,而不是真正的任何Ratio东西 AFAIK。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM