Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to do bit shifts and masks in haskell?

I'm writing a routine to determine whether the high 16 bits of a 32-bit integer have more bits set, or the low bits.

In C, I would write this:

bool more_high_bits(int a) {
  if ((a >> 16) == 0) return false;    // no high bits
  if ((a & 0xFFFF) == 0) return true;  // no low bits

  // clear one high bit and one low bit, and ask again
  return more_high_bits(a&(a - 0x10001));
}

So in Haskell, I'm trying this:

more_high_bits a=if (a `shiftR` 16) /= 0 then 0 else
                 if ((.&.) a 65535) /= 0 then 1 else
                 more_high_bits((.&.) a (a-65537))

But it just times out.

What am I doing wrong? What's the more idiomatic way to do this? Please don't code away the shift or the & because I'd like to know how I "should" be using these.

Addendum: I tried this code out on an haskell compiler:

http://www.tutorialspoint.com/compile_haskell_online.php

import Data.Bits

g a=if (a `shiftR` 16) == 0 then 0 else
    if ((.&.) a 65535) == 0 then 1 else
    g((.&.) a (a-65537))

main = print (g(237))

But it tells me "No instance for (Bits a0) arising from a use of 'g' The type variable 'a0' is ambiguous"

What is "a0"??

like image 685
jorgbrown Avatar asked Feb 09 '23 10:02

jorgbrown


1 Answers

Here's a pretty direct translation of your C code to Haskell:

import Data.Word
import Data.Bits

more_high_bits :: Word32 -> Bool
more_high_bits a
    | (a `shiftR` 16) == 0 = False
    | (a .&. 0xFFFF)  == 0 = True
    | otherwise            = more_high_bits (a .&. (a - 0x10001))

Your attempt has /= where the C version has ==, which inverts the condition.

a0 is the type variable that the type checker automatically created for your use of g 237. It doesn't know which type you mean because 237 could be any numeric type at all, and g works with all numbers that support bitwise operations and equality. The list of types you could have meant includes (but is not limited to) Int, Integer, Word, ...

like image 131
melpomene Avatar answered Feb 19 '23 13:02

melpomene