Reputation: 33
I'm trying to declare a function where the numerical argument can only be an Int
.
I'm writing a function that'll discard every n
th element of a list. I'm using modulo arithmetic, but the mod
function will only take a type of Int
and I can't figure out how to guarantee my number will satisfy that.
My code is as follows:
dropEvery :: (Num n, Eq n) => n -> [a] -> [a]
dropEvery m list = [list !! i | i <- [1 .. length list], i `rem` m /= 0]
I've run :info mod
and replaced Num n
with Real n, Enum n and Integral n
(all the constraints I can see in the output) but this still doesn't guarantee the compiler that n
will be an Int
.
I'm sure there are solutions to this problem which don't use such a imperative approach, but I'd like to use this opportunity to learn a bit more about how types and constraints work in Haskell by solving this problem head-on.
Upvotes: 2
Views: 69
Reputation: 11628
You just have to use the actual type Int
instead of using constrains (Num n, Eq n)
. (Note that Haskell uses 0-based list indexing so I had to add a -1
for it to work correctly.)
dropEvery :: Int -> [a] -> [a]
dropEvery m list = [list !! (i-1) | i <- [1 .. length list], i `rem` m /= 0]
main = print $ dropEvery 3 [1..20]
If you want to avoid the !!
you can also avoid explicitly finding the length of the list by using zip
which replaces your list comprehension with
[ l | (l,i) <- zip list [0..], (i+1) `rem` m /= 0]
Upvotes: 6