0

I had to write my own unzip function. Now I have to write examples. But I don't get it to work with empty lists:


example_unzip_1 = unzip [] == ([],[])

I tried several things, but what I most expected to work was:


example_unzip_1 = unzip []::[(a,b)] == ([],[])::([a],[b])

I know the error is about the types, but I don't know what to do.

edit

I updated the expressions because the comments showed I was not clear enough.

example_unzip_1 should be true.

and the definition of the function:

DEFINITION

> unzip [] = ([],[])
> unzip ((a,b):xs) = (a:as, b:bs)
>   where (as, bs) =  unzip xs
peni4142
  • 426
  • 1
  • 7
  • 26
  • 2
    In Haskell, you define a new entity with a single '=' sign. This is known as the assignment operator. Like: `newEntity = definition of new entity` ; the double equal sign "==" is only used to test whether two *already defined* entities happen to be equal, just like in the C and C++ languages. – jpmarinier Dec 10 '20 at 11:10
  • Reading your post, I can't quite tell if your code is the implementation of your unzip or two examples that you think should be true. Can you post the code for your function along with the type signature that it has? – Marc Talbot Dec 10 '20 at 11:27
  • 1
    `unzip [] = ([],[])` with a single equals sign is a perfectly valid line of code. Now you also need another equation to handle non-empty input lists. – chi Dec 10 '20 at 11:50
  • Sorry guys. My question seemed not to be clear enough. – peni4142 Dec 10 '20 at 12:23

1 Answers1

1

If you type unzip [] == ([],[]) into GHCi, it will correctly evaluate to True, but when you add the line example_unzip_1 = unzip [] == ([],[]) to a file and try to open it, you get a type error. Why is this? In the GHC technical jargon, this has to do with "the monomorphism restriction", but what this means practically is that GHC doesn't know what type of lists you're using.

In GHCi, the interpreter automatically does some defaulting for you. If you type in a number like 3, it prints out 3. But, if you ask for the type of 3 with :t 3, you see that it says 3 :: Num p => p. So, if all GHCi knows is that 3 is a type that is an instance of Num, how was it able to show it? And, why doesn't it show it as 3.0, assuming you typed in a Float? Well, in the absence of further information, GHCi "defaults" the type to Integer and goes ahead and uses the Show instance for Integer. When you type unzip [] == ([],[]), it defaults the types of the lists too, giving them a concrete type and an Eq instance.

You're on the right track with your second attempt, (that is, example_unzip_1 = unzip []::[(a,b)] == ([],[])::([a],[b])), but there are two problems here. First, GHC is a little finicky about type variables, and in this case, because you haven't introduced your type variables with the forall keyword (which also requires using some language extensions, probably ScopedTypeVariables), GHC doesn't actually realize that the a on the left is the same as the a on the right. But regardless, GHC still won't know which actual types to use when it does the equality check!

The way to fix this is to use actual concrete types. For instance, you could write:

example_unzip_1 = unzip []::[(Int,())] == ([],[])::([Int],[()])

This will properly type check. In fact, because of GHC's good type inference, you only need one type annotation, so you can simplify this to:

example_unzip_1 = unzip []::[(Int,())] == ([],[])
DDub
  • 3,884
  • 1
  • 5
  • 12