Search code examples
haskellmodulo

Haskell modulo similar to JavaScript (takes sign into account and works for non-integers)


In JavaScript:

console.log(13 % 5);
// Expected output: 3

console.log(-13 % 5);
// Expected output: -3

I need the same in Haskell. I did

:{
modulo :: Double -> Int -> Double
modulo a p = 
    let p' = fromIntegral p
    in
    if a > 0 
        then a - fromIntegral(p * floor(a/p'))  
        else a - fromIntegral(p * ceiling(a/p'))
:}

That seems to work (at least I find the same results as the JavaScript ones). Is there a better way?

Contrary to rem, it should work for a Double a:

ghci> modulo (-13.5) 5
-3.5

Solution

  • This already exists, this is rem :: Integral a => a -> a -> a:

    ghci> 13 `rem` 5
    3
    ghci> (-13) `rem` 5
    -3
    

    Haskell has two "pairs" of functions regarding division and modulo: div and mod, which truncate towards negative infinity; and quot and rem which truncate towards zero.

    or for RealFrac types:

    fracRem :: (RealFrac a, Integral b) => a -> b -> a
    fracRem x y = x - fromIntegral (y * (truncate x `quot` y))