3
votes

For

x :: Integer -> [a] -> [a]
x = take

y :: Integer -> [a] -> [a]
y _ [] = []
y n xs = take n xs

both Hugs and GHC report type errors:

ERROR "test.hs":5 - Type error in application
*** Expression     : take n xs
*** Term           : n
*** Type           : Integer
*** Does not match : Int

ERROR "test.hs":8 - Type error in explicitly typed binding
*** Term           : x
*** Type           : Int -> [a] -> [a]
*** Does not match : Integer -> [a] -> [a]

This is due to the fact that "take" has the signature "Int -> ...". Is there a way to tell the type system to either convert Integer to Int directly (without fromIntegral), or preferably (to keep the non-constrained size of Integer) to "construct" a version of take (or any other function explicitly using Int) for Integer? Or do I have to write my own versions of Prelude-Functions? Currently, my code is either littered with fromIntegral (and doesn't run if the Integer size exceeds the dimensions of Int) or with trivial re-implementations of standard functions, and that feels very clunky.

2

2 Answers

4
votes

Use genericTake from Data.List instead. The "generic" list functions receive Integer instead of the Int.

In the future, if you want to search for Haskell functions by type signature you can use Hoogle


In a more general sense, if all you want to do is add a conversion step you can use the built in composition operator to easily create your own functions.

--explicit type signature to force the less general types...
integerToInt :: Integer -> Int
integerToInt = fromIntegral

myGenericTake = take . integerToInt

--You can now use myGenericTake throughout the code.
1
votes

Haskell takes the approach of not making any implicit casts. So when you are stuck with functions like take, you simply need to perform the explicit cast using fromIntegral or similar.

If that bugs you, then voice your opinion about improving Prelude. You would certainly not be alone in hoping for improved Prelude functions.