I'm used to using % to mean "modulo" in other languages. In Haskell, we have to use mod x y
or x `mod` y
. So, what is this symbol used for in Haskell?

- 1,486
- 4
- 18
- 28
-
1Show an example of its use. I don't remember any uses for it offhand, but it's very possible to make your own definition of it, so libraries may define it. – Carcigenicate Feb 19 '19 at 00:59
-
2it's in `Data.Ratio`, see here: http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Ratio.html#v:-37- (Unless of course there is another definition of `%` in another library, as is entirely possible.) – Robin Zigmond Feb 19 '19 at 01:03
5 Answers
With a quick look on Hoogle, you can see that %
is an infix function defined as
(%) :: Integral a => a -> a -> Ratio a
and as you can guess it is part of the Data.Ratio
library, which mostly deals with ratios (i.e.: fractions). 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

- 2,160
- 12
- 29
-
Never heard of Hoogle. I am new to Haskell. I searched via DDGo, and not one article mentioned Data.Ratio. This resource was not included in general search results. See: https://duckduckgo.com/?q=operator+haskell&t=ffab&atb=v155-6&ia=software – Ryan Feb 21 '19 at 22:22
-
Is there a way to look up those type definitions for Data.Ratio in GHCi/Prelude? I already tried `:t %` to no avail – Ryan Feb 21 '19 at 22:24
-
1@Ryan, Hoogle at https://www.haskell.org/hoogle/ is a search engine for Haskell libraries. you can reach it at that link and you can then search for any function, some function description and -- the most important -- function types. As I said, `%` is part of the `Data.Ratio` library, so before you can use it in the GHCi -- including `:t`, you need to import it by `import Data.Ratio`. Then you can see the type. Remember also you can use `:info` that sometimes gives you more info than just `:t` – Lorenzo Feb 21 '19 at 22:39
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).
As the most typical case, %
is provided as the constructor of the Ratio
type by Data.Ratio module.
Try the code below on GHCi to make sure that %
is provided by 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.
% 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 (i.e.: fractions). Its code is
x % y = reduce (x * signum y) (abs y)
thus given two integrals (x,y) , it returns an irreducible fraction x/y

- 1,486
- 4
- 18
- 28

- 1,364
- 9
- 17
Searching for (%)
on Stackage Hoogle, it appears that Data.Ratio
defines the %
operator as constructing a Ratio
value from a numerator and denominator. A GHCi example:
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

- 8,337
- 2
- 22
- 51
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
. (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.)
Note, however, that Integral
defines both mod
and rem
functions. 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.
Also, languages use different definitions for %
, so either (%) = mod
or (%) = rem
had the potential for confusing someone.

- 497,756
- 71
- 530
- 681
-
There's also a nice version (I think maybe in Python?) that guarantees a positive result regardless of the signs of the operands, as well as guaranteeing `q * n + r = m`. – dfeuer Feb 20 '19 at 01:12
-
-
Huh. Got that wrong. R6RS Scheme's `mod` does it "Euclidean style", as does PureScript (which used to do it Knuth style but switched). – dfeuer Feb 20 '19 at 01:59
Found this in "Old School" Davies Introduction to Functional Programming Systems Using Haskell. (He constantly compares Haskell to Pascal.) It's a simulation of stack arithmetic
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.

- 2,137
- 18
- 28