Haskell basic Show instance for simple recursive datatype not working - haskell

i have a simple Problem. This Code looks perfectly fine to me.
main = do
print("10-2")
let a = L
let b = E "abc" a
print(a)
print(b)
data List a = L | E a (List a)
instance (Show a) => Show (List a) where
show L = "Empty"
show (E a list) = (show a)++ (show list)
But it produces following error:
10-2.hs:5:5:
No instance for (Show a0) arising from a use of `print'
The type variable `a0' is ambiguous...
I cant find the Problem. Thanks for the Help!

It's the same error you will get if you try to compile this simple program:
main = print []
What? Haskell cannot print an empty list? That's correct, it cannot. That is, unless the type of the list element is known. It is not known at this case, so compilation fails. In order to see why, run these two programs:
main = print ([] :: [Int])
main = print ([] :: [Char])
The output is different, though the only difference between these programs is the type of an empty list.
However, if you try this same ambiguous program in ghci it will print [] just fine!
Prelude> let main = print []
Prelude> main
[]
Prelude>
This is because ghci has a slightly more liberal set of defaulting rules than ghc. So if you load your data type definition to ghci and say print L at the prompt, ghci will happily obey:
[1 of 1] Compiling Main ( h.hs, interpreted )
Ok, modules loaded: Main.
*Main> print L
Empty
*Main>

In your function main, when you write let a = L, the type of a is just List a0. When the compiler tries to know which version of the Show instance it has to use, all types fits, because a's type is not fully defined. If you delete the line print a however, you will see that print b will work, because b's type can only be List String, and the compiler knows exactly which version of show it has to use.
main = do
print "10-2"
let a = L
let b = E "abc" a
-- print a
print b
Try writing print [] and you will see that the compiler gives you the same kind of error.
In ghci however, if you just type print L or print [], it will not prompt an error. I don't know why this is happening.

As the others already said, you need to give your List a type, even if the data Constructor doesn't need it to create itself.
So Try out:
print (L :: List Int)
or whatever you like to just print a your String of the Show Instance of (List a)

Related

Haskell. Matching pattern Problem. Cannot put in IO value of function with empty list "print $ note1 []" - failing to compile

Haskell. Matching pattern Problem. Cannot put in IO value of function with empty list
print $ note1 []
failing to compile, but works fine in ghci ?!
Also the print $ note1 [1] works fine and compiles fine too. The problem only with empty list:
print $ note1 []
(N.B. I am new in Haskell)
I
have a matching pattern function
note1 :: (Show a) => [a] -> String
note1 [] = "Empty"
note1 (x:[]) = "One"
But print $ note1 [] fails to compile, but perfectly works in ghci interpreter?!
I am using stack 2.3.1 and ghc 8.8.3 on MacOS.
This is the compilation error produced by compiler.
/Users/admin1/Haskell/PROJECTS/orig1/src/Lib.hs:18:13: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘note1’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 15 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the second argument of ‘($)’, namely ‘note1 []’
In a stmt of a 'do' block: print $ note1 []
In the expression:
do putStrLn "someFunc"
putStrLn $ show (1)
putStrLn $ show $ length ("a" :: String)
putStrLn $ show (length' "a")
.... |
18 | print $ note1 []
The problem is the (unnecessary, in this case) Show a constraint on note1. Here's what happens. When GHC is typechecking print $ note1 [], it needs to work out which Show instance to use with note1. That's typically inferred from the type of elements in the list that it's passed. But the list it's passed ... doesn't have any elements. So the typechecker has no particular way to choose an instance, and just gives up. The reason this works in GHCi is that GHCi, by default, enables the ExtendedDefaultRules language extension, which expands the type defaulting rules. So instead of throwing up its hands, the type checker picks the type () for elements of the list, and everything works. Something sort of similar is going on when you use [1]. In that case, the standard defaulting rule comes into play: numeric types default to Integer, so the typechecker picks that type.
How should you fix this? You could manually write
print $ note1 ([] :: [()])
to make your code compile, but if that's your real code, you'd be much better off removing the unnecessary constraint:
note1 :: [a] -> String
note1 [] = "Empty"
note1 (x:[]) = "One"
As a side note, since you don't use the x variable, it's best to make that fact explicit by either using the special _ pattern:
note1 :: [a] -> String
note1 [] = "Empty"
note1 (_:[]) = "One"
or prefixing the variable name with an underscore:
note1 :: [a] -> String
note1 [] = "Empty"
note1 (_x:[]) = "One"
This indicates, both to other programmers (such as yourself a few hours later) and the compiler, that you are intentionally not using that value.
Additionally, you can (and probably should) use list syntax to clarify the second pattern:
note1 [_] = "One"
Finally, the note1 function has a bit of a problem: if you pass it a list with more than one element, it'll produce a pattern match failure. Whoops! It's usually better to write total functions when you can. When you can't, it's generally best to use an explicit error call to indicate what went wrong. I recommend compiling your code with the -Wall flag to help catch mistakes.

Haskell Monad Beginner

Hello I have a code which I'm trying to understand:
zipM:: Monad m => [m a] -> [m b] -> m [(a,b)]
zipM [] list = return []
zipM list [] = return []
zipM (hFirst:tFirst) (hSecond:tSecond) = do
rest <- zipM tFirst tSecond
headUnpacked <- unpack hFirst hSecond
return (headUnpacked : rest) -- rest = Just []
unpack ::Monad m => m a -> m b -> m (a,b)
unpack first second = do
fi <- first
se <- second
return (fi, se)
Generally I got a point but still have problem at two moments.
How to call 'unpack' in console ? I tried unpack (Just 5) and it's causing an error.
Since 'rest' is 'Just []' how can I perform simple list add?
I tried (Just 4): (Just []) and also (Just [1,2]): (Just [2,3]) both of which result in errors.
I'll be most grateful if someone will show with some basic explanation how to perform this two actions.
You can use unpack in GHCi like this:
Prelude> unpack (Just 5) (Just 42)
Just (5,42)
Prelude> unpack [[42,1337],[123]] [["foo"],["bar","baz"]]
[([42,1337],["foo"]),([42,1337],["bar","baz"]),([123],["foo"]),([123],["bar","baz"])]
Prelude> :m +Data.Monoid
Prelude Data.Monoid> unpack (Product 7, "foo") (Product 6, "bar")
(Product {getProduct = 42},("foo","bar"))
Notice that the function works with any Monad, not only Maybe. The above GHCi session demonstrates that by also calling unpack with two lists, and two tuples (which are Monad instances when the first element is a Monoid).
There's nothing inherently wrong with the expression unpack (Just 5):
Prelude Data.Monoid> :t unpack (Just 5)
unpack (Just 5) :: Num a => Maybe b -> Maybe (a, b)
The reason you see an error is because, as you can see from the above type inquiry, the expression is a function. Again, there's nothing wrong with functions, but GHCi doesn't know how to render functions because it relies on the Show type class to turn expressions into printable values, and functions don't have Show instances.
To address the second question, rest isn't Just []. First, Just isn't a type, but a data constructor, but secondly, even if you meant Maybe [a], that's not necessarily true, because you don't know whether or not the Monad in question is Maybe or some other Monad.
Finally, as far as I can tell, rest is the result of calling unpack, the result of which has the type Monad m => m (a,b). Since rest is bound using do notation, it must, then, have the type (a,b), unless I'm mistaken.

Haskell ASCII codes

I'm trying to make a function that takes an a (which can be any type: int, char...) and creates a list which has that input replicated the number of times that corresponds to its ASCII code.
I've created this:
toList n = replicate (fromEnum n) n
When trying to use the function in the cmd it says it could match the expected type int with char, however if i use my function directly in the cmd with an actual value it does what it's supposed.
What i mean is: toList 'a' --> gives me an error
replicate (fromEnum 'a') 'a' --> gives a result without problem
I've loaded the module Data.Char (ord)
How can I fix this, and why does this happens?
Thanks in advance :)
What you're missing is a type declaration. You say that you want it to be able to take any type, but what you really want is toList to take something that is an instance of Enum. When you play around with it in GHCi, it'll let you do let toList n = replicate (fromEnum n) n, because GHCi will automatically pick some defaults that seem to make sense, but when compiling a module with GHC, it won't work without the type declaration. You want
toList :: (Enum a) => a -> [a]
toList n = replicate (fromEnum n) n
The reason why you have to have the (Enum a) => in the type signature is because fromEnum has the type signature (Enum a) => a -> Int. So you see it doesn't just take any type, only those that have an instance for Enum.

No instance for (Show a0) arising from a use of `print' The type variable `a0' is ambiguous

data NestedList a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem element) = [element]
flatten (List []) = []
flatten (List (first:rest)) = flatten first ++ flatten (List (rest))
main = print $ flatten $ List []
I wrote the above seen code in haskell. When I execute this with any other parameter, for example
main = print $ flatten $ List [Elem 1, Elem 2]
main = print $ flatten $ Elem 1
It gives
[1, 2]
[1]
respectively.
It fails when I execute it with an empty List.
main = print $ flatten $ List []
Error message
No instance for (Show a0) arising from a use of `print'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 23 others
In the expression: print
In the expression: print $ flatten $ List []
In an equation for `main': main = print $ flatten $ List []
Questions
Why does it fail and how can I fix this?
Should I change my NestedList definition to accept an empty List? If so, how do I do that. Its quite confusing.
The list type is polymorphic. Since you don't supply an element, just the empty list constructor [], there's no way to infer what list type this is.
Is it: [] :: [Int]
or [] :: [Maybe (Either String Double)]. Who's to say?
You are. Supply a type annotation to resolve the polymorphism, then GHC can dispatch to the correct show instance.
E.g.
main = print $ flatten $ List ([] :: [Int])
To add to the answers here already, you may object "but what does it matter what type of things my list contains? it doesn't have any of them in it!"
Well, first of all, it is easy to construct situations in which it's unclear whether or not the list is empty, and anyway type checking hates to look at values, it only wants to look at types. This keeps things simpler, because it means that when it comes to deal with values, you can be sure you already know all the types.
Second of all, it actually does matter what kind of list it is, even if it's empty:
ghci> print ([] :: [Int])
[]
ghci> print ([] :: [Char])
""
The problem is the compiler can't know the type of flatten $ List []. Try to figure out the type yourself, you'll see it's [a] for some a, whilst print requires its argument to be an instance of Show, and [a] is an instance of Show if a is an instance of Show. Even though your list is empty, so there's no need for any constraint on a to represent [], there's no way for the compiler to know.
As such, putting an explicit type annotation (for any type for which an instance of Show exists) should work:
main = print $ flatten $ List ([] :: [NestedList Int])
or
main = print $ flatten $ List ([] :: [NestedList ()])
or
main = print fl
where
fl :: [()]
fl = flatten $ List []
[] can be a list of floats, strings, booleans or actually any type at all. Thus, print does not know which instance of show to use.
Do as the error message says and give an explicit type, as in ([] :: [Int]).

No instance for (Show ([(Char, Char)] -> Char))

So I have to make a function that finds a pair with its 1st letter and returning the 2nd letter.
I actually found one answer but with the map function and I couldn't get it.
lookUp :: Char -> [(Char, Char)] -> Char
lookUp x [] = x
lookUp x ( ( st,nd ): rst) | st == x = nd
| otherwise = lookUp x rst
And I get this message:
No instance for (Show ([(Char, Char)] -> Char))
arising from a use of `print'
Possible fix:
add an instance declaration for (Show ([(Char, Char
In a stmt of an interactive GHCi command: print it
Your code is fine, you just need to supply all the arguments at the ghci prompt, eg
lookUp 'c' [('b','n'), ('c','q')]
Should give you 'q'.
It's complaining that it can't show a function. Any time it says it doesn't
have a Show instance for something with -> in, it's complaining it can't
show a function. It can only show the result of using the function on some data.
When you give it some, but not all data, Haskell interprets that as a new function
that takes the next argument, so
lookUp 'c'
is a function that will take a list of pairs of characters and give you a character.
That's what it was trying to show, but couldn't.
By the way, almost every time you get a "No instance for..." error, it's because
you did something wrong with the arguments - missed some out, put them in
the wrong order. The compiler's trying to be helpful by suggesting you add
an instance, but probably you just need to check you supplied the write type
of arguments in the right order.
Have fun learning Haskell!
It seems that you typed something like this in ghci:
*Main> lookUp 'c'
An expression like lookUp 'c' is a partial evaluation / curried form of the lookUp function. It's type is:
*Main> :t lookUp 'c'
lookUp 'c' :: [(Char, Char)] -> Char
which is the exact type that ghci says there is no Show instance for.
To test your function, be sure to supply both x and the the list of Char pairs:
*Main> lookUp 'c' [ ('a','A'), ('b','B'), ('c','C') ]
'C'

Resources