Why does the integral constraint require Integral to call duration?

I just started programming in Haskell, and I solve 99 Haskell problems , and when I was almost done with the 10th, you ran into this problem:

-- Exercise 9 pack :: Eq a => [a] -> [[a]] pack [] = [] pack list = let (left,right) = span (== head list) list in left : pack right -- Exercise 10 encode :: (Eq a, Integral c) => [a] -> [(c, a)] encode [] = [] encode list = map (\x -> (length x, head x)) (pack list) -- this doesn't work ^^^^^^^^ 

An error has occurred:

 Could not deduce (c ~ Int) from the context (Eq a, Integral c) bound by the type signature for encode :: (Eq a, Integral c) => [a] -> [(c, a)] at C:\fakepath\ex.hs:6:11-47 `c' is a rigid type variable bound by the type signature for encode :: (Eq a, Integral c) => [a] -> [(c, a)] at C:\fakepath\ex.hs:6:11 In the return type of a call of `length' In the expression: length x In the expression: (length x, head x) 

I managed to fix this by inserting the function I read about into Teach you Haskell : fromIntegral .

 encode list = map (\x -> (fromIntegral $ length x, head x)) (pack list) 

So my question is: why is this needed ?

I ran :t length and got [a] -> Int , which for me is a pretty specific type that must satisfy the Integral c constraint.

+4
source share
1 answer

A signature of the type (Eq a, Integral c) => [a] -> [(c, a)] means that the function works for any types a and c in the corresponding classes. The actual type is used on the call site.

As a simple example, consider the type of an empty list:

 :t [] [a] 

This means that [] represents an empty String list and an empty Int list, an empty Maybe [Maybe Bool] list, and any other types that you can imagine. We can imagine how to wrap this in a normal identifier:

 empty :: [a] empty = [] 

empty obviously works just like [] . Thus, you can see that the following definition does not make sense:

 empty :: [a] empty = [True] 

after all, [True] never be [Int] or [String] or any other empty list you want.

The idea here is the same, except that I have restrictions on the class and variables. For example, you can use encode to return a list of [(Integer, String)] , since Integer also in the Integral class.

So, you have to return something polymorphic, which can be any Integral - just what fromIntegral does. If you just returned Int , encode will only be used as Int , not Integral .

+9
source

Source: https://habr.com/ru/post/1495338/


All Articles