Haskell instance: how could this be some valid code? - haskell

While I was writing a small example of the Show instance, I had made an indentation error:
module Main where
data B= B0|B1
instance Show B where
show B0="0"
show B1="1"
main=print B0
Where, clearly, the working code is:
module Main where
data B= B0|B1
instance Show B where
show B0="0"
show B1="1"
main=print B0
I was expecting to get a compile error on the first one, but instead I could run it and it ended up in:
example.hs: stack overflow
Why does this code even compile?
Also, why is this a runtime error only (which, if stack is unconstrained, fills up your RAM) and not a compilation error?

The body of an instance can be empty. You can leave out the where clause:
instance Show B
but you can also include it:
instance Show B where
-- nothing here
This can be useful for type classes that provide default implementations for the methods, perhaps based on generic programming facilities. For example, with the aeson package, the usual way of defining instances to convert to and from JSON is to use generics and empty instances:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
data Person = Person {
name :: Text
, age :: Int
} deriving (Generic, Show)
-- these empty instances use Generics to provide a default implementation
instance ToJSON Person
instance FromJSON Person
In your program, by leaving out the indentation, you've defined an instance Show B with no method definitions (and -Wall would generate a "missing method" warning telling you that it did not meet the minimal requirements for the instance). The unindented show is providing a new top-level definition for show, unrelated to the show in the Show type class.
You haven't used show explicitly. Instead, you've used it implicitly via print, which always calls the show from the type class, ignoring your top-level definition, so your crashing program is equivalent to:
data B = B0 | B1
instance Show B
main = print B0
This generates a stack overflow because there are default definitions of show and showsPrec that are used when no specific instances are given:
show x = shows x ""
showsPrec _ x s = show x ++ s
which operate together with the top-level function shows (not part of the type class):
shows = showsPrec 0
This works great when at least one of show or showsPrec is defined in the instance, and then the other gets a sensible definition, but if neither is defined, this creates an infinite recursive loop between these three functions.
Also, note that the following program would tell you show was ambiguous which would make it clearer what was going on.
module Main where
data B= B0|B1
instance Show B where
show B0="0"
show B1="1"
main=putStrLn (show B0) -- instead of print

Since you did not indent show, it means this does not belong to the instance for Show, you program is thus equivalent to:
instance Show B where -- ← no implementations
show B0 = "0"
show B1 = "1"
You here thus construct another function show, that has nothing to do with the Show typeclass, but simply has the same name.
Show defines three functions showsPrec :: Show a => Int -> a -> String -> String, show :: a -> String -> String, and showList :: [a] -> String -> String. showsPrec is often used since it has a precedence system to use parenthesis.
As a result show is impelemented in terms of showsPrec and showsPrec is implemented in terms of show:
class Show a where
{-# MINIMAL showsPrec | show #-}
-- …
showsPrec :: Int
-> a
-> ShowS
-- …
show :: a -> String
-- …
showList :: [a] -> ShowS
showsPrec _ x s = show x ++ s
show x = shows x ""
showList ls s = showList__ shows ls s
-- …
shows :: (Show a) => a -> ShowS
shows = showsPrec 0
It is thus sufficient to implement showsPrec or show, that is why there is a {-# MINIMUM showsPrec | show #-} pragma at the top of the type class.
If you do not implement any of the two, then the compiler will raise a warning, and use thus the basic implementations, but that will lead to nothing, since show will call showPrec, which will then call show, until eventually the stack is exhausted.

Related

Overlapping instance for Show

Suppose we have the following:
{-# LANGUAGE FlexibleInstances #-}
module Sample where
newtype A a =
A a
deriving (Show)
newtype L a =
L [a]
class ListContainer l where
getList :: l a -> [a]
instance ListContainer L where
getList (L l) = l
instance (Show a, ListContainer l) => Show (l a) where
show = const "example"
With this code, ghc complains:
warning: [-Wdeferred-type-errors]
• Overlapping instances for Show (A a)
    arising from a use of ‘GHC.Show.$dmshowList’
  Matching instances:
    instance (Show a, ListContainer l) => Show (l a)
      -- Defined at /.../src/Sample.hs:18:10
    instance Show a => Show (A a)
      -- Defined at /.../src/Sample.hs:7:13
• In the expression: GHC.Show.$dmshowList #(A a)
  In an equation for ‘showList’:
      showList = GHC.Show.$dmshowList #(A a)
  When typechecking the code for ‘showList’
    in a derived instance for ‘Show (A a)’:
    To see the code I am typechecking, use -ddump-deriv
  In the instance declaration for ‘Show (A a)’
warning: [-Wdeferred-type-errors]
• Overlapping instances for Show (A a)
    arising from a use of ‘GHC.Show.$dmshow’
  Matching instances:
    instance (Show a, ListContainer l) => Show (l a)
      -- Defined at /.../src/Sample.hs:18:10
    instance Show a => Show (A a)
      -- Defined at /.../src/Sample.hs:7:13
• In the expression: GHC.Show.$dmshow #(A a)
  In an equation for ‘show’: show = GHC.Show.$dmshow #(A a)
  When typechecking the code for ‘show’
    in a derived instance for ‘Show (A a)’:
    To see the code I am typechecking, use -ddump-deriv
  In the instance declaration for ‘Show (A a)’
I can understand that it thinks type a can either derive Show, or derive ListContainer, which may result in Show.
How do we avoid that?
I understand that there exists a function showList, but its signature is a bit foreign. I do already have a function that I intend to use to display certain lists, which returns String directly.
I can understand that it thinks type a can either derive Show, or derive ListContainer, which may result in Show.
That is not what it thinks.
When Haskell chooses class instance, it doesn't look at instance constraints at all. All it considers when choosing an instance is the instance head (the thing that comes right after class name).
In your Show instance, the instance head is l a. This instance head matches A a (by assuming l = A). It also matches a lot of other things by the way - for example, it matches Maybe a (where l = Maybe), and Either b a (with l = Either b), and Identity a, and IO a - pretty much every type with a type parameter, come to think of it. It doesn't matter that neither A nor Maybe nor IO have an instance of ListContainer, because like I said above, Haskell doesn't look at constraints when choosing instances, only at instance heads.
It is only after finding a matching instance (by matching on its head) that Haskell will check if that instance's constraints are in fact satisfied. And will complain if they aren't. But it will never go back and try to pick another instance instead.
So coming back to your example: since A now has two matching Show instances - its own derived one and the Show (l a) one that you wrote, - the compiler complains that they are overlapping.
In your example you can just remove instance (Show a, ListContainer l) => Show (l a) and add deriving (Show) to L definition.
Alternatively you can remove deriving (Show) from A definition.
If you want you code behave as it is now remove deriving (Show) and implement it explicitly
instance {-# OVERLAPPING #-} Show a => Show (A a)
where
show (A a) = "A " ++ show a

In Haskell, how to derive such a custom class automatically?

The codes looks like this:
class MyAnd a where
myAnd :: (Show a) => a -> a -> String
x `myAnd` y = (show x) ++ " and " ++ (show y)
data TrafficLight = Red | Yellow | Green deriving(Show, MyAnd)
Here MyAnd is a type class which has a function myAnd, I thought it is generic and the only constraint is the a has to has an instance of Show class..
In the TrafficLight type, it already derived from Show type class. However, when I compiled the codes, the compiler complains
Can't make a derived instance of ‘MyAnd TrafficLight’:
‘MyAnd’ is not a derivable class
In the data declaration for ‘TrafficLight’
Failed, modules loaded: none.
Does anyone have ideas about this?
You can't use deriving with user-defined classes. Usually deriving automatically generates code for the given class's methods, which is only possible because the compiler knows what the methods are supposed to do and can thus generate suitable implementations based on your type's structure. This is obviously not possible for user-defined classes as the compiler has no way of knowing how the methods are supposed to behave.
In your case it looks like all you want is to use the default implementations of the one method your class has, so no implementation would need to be generated by the compiler. Of course that means that deriving isn't necessary at all and you can just use an instance declaration without a body.
PS: If you'll always want to use the default implementation of the method, it might make the most sense not to use a class at all, but just define myAnd as a function.
For this specific problem, you can simply avoid defining a custom class:
data TrafficLight = Red | Yellow | Green deriving Show
myAnd :: (Show a) => a -> a -> String
x `myAnd` y = (show x) ++ " and " ++ (show y)
Now, myAnd is applicable to TrafficLights (as well as all the other Showable types).
Found this question while trying to figure out how to use GHC's DeriveAnyClass extension, which had only been out for three weeks back when this was asked.
Using it, the following works as you'd expect:
{-# LANGUAGE DeriveAnyClass #-}
class Show a => MyAnd a where
myAnd :: a -> a -> String
x `myAnd` y = (show x) ++ " and " ++ (show y)
data TrafficLight = Red | Yellow | Green deriving (Show, MyAnd)
Should be used with caution though, as it will literally derive any class, creating empty instances when necessary.

Can there be a special Show instance for a tuple?

I am working with so-called tokens which are tuples with a string and a tag that I wish I could render on the screen in the following format: [TAG: VALUE] I cannot do that because I am not doing something right. Here is the setup:
type Token value tag = ([value], tag)
data Tag = Whitespace | Alpha | Digit | Punctuation | Terminal
instance Show Tag where
show Alpha = "A"
show Whitespace = "W"
show Digit = "D"
show Punctuation = "P"
show Terminal = "|"
type TextToken = Token Char Tag
instance Show TextToken where
show (values, tag) = "[" ++ show tag ++ ": " ++ values ++ "]"
Which crashes at compiling:
Illegal instance declaration for `Show TextToken'
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Show TextToken'
Then I tried replacing the instance with the following:
instance Show ([Char], Tag) where
show (values, tag) = "[" ++ show tag ++ ": " ++ values ++ "]"
And got the same problem again:
Illegal instance declaration for `Show ([Char], Tag)'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Show ([Char], Tag)'
Is there a way to make it work?
You'll want to use a newtype
newtype Tag a b = Tag (a, b)
instance (Show a, Show b) => Show (Tag a b) where
show (Tag (a, b)) = "[" ++ show a ++ ": " ++ show b ++ "]"
You're running into several instance resolution quibbles all at once.
Without the {-# LANGUAGE TypeSynonymInstances #-} pragma, you cannot use type synonyms in instance definitions... even if they're perfectly clear. Enabling it is fine, it's simply not Haskell 98.
When using complex, nested, or multiparameter types in instance definitions, you frequently run afoul of the overly restrictive Haskell 98 instance definition. In many cases this is fine, so enabling the {-# LANGUAGE FlexibleInstances #-} pragma will allow these OK opportunities.
Finally, dangerously, there's already a Show instance for ([Char], Tag), the polymorphic one instance Show (a, b) with a ~ [Char] and b ~ Tag. This means you'll run afoul of the OverlappingInstances warning.
You can disable this by telling GHC to allow OverlappingInstances using another pragma {-# LANGUAGE OverlappingInstances #-} but since it can cause very strange runtime behavior for both yourself and others who use your code, its use is highly discouraged.
Generally, if you're trying to "specialize" an instance declaration to a particular type, you need the general case to not exist.
newtype Tup a b = Tup (a, b)
instance Show (Tup Int Int) where
show (Tup tup) = show tup
instance Show (Tup String Int) where
show (Tup (s, int)) = s ++ ": " ++ show int
>>> show ("foo", 3)
foo: 3
>>> show (2, 3)
(2, 3)
>>> show ("foo", "bar")
No instance for...
The thing that you really need to decide is if you want different instances for different sorts of Token. If you do, then use a newtype (or compiler option, as some suggest). If you don't, then make Token a data and define your instance on the generic Token type.
To make a newtype wrapper:
newtype TextToken = TextToken (Token Char Tag)
then declaring the Show instance for the wrapper:
instance Show TextToken where
In your case I'd still recommend changing
type Token value tag = ([value], tag)
to
data Token value tag = Token [value] tag
because you have a record type anyway, so you might as well make it explicit.

Showing the type A -> A

data A = Num Int
| Fun (A -> A) String deriving Show
instance Show (Fun (A -> A) String) where
show (Fun f s) = s
I would like to have an attribute for a function A -> A to print it, therefore there is a String type parameter to Fun. When I load this into ghci, I get
/home/kmels/tmp/show-abs.hs:4:16:
Not in scope: type constructor or class `Fun'
I guess this could be achieved by adding a new data type
data FunWithAttribute = FA (A -> A) String
adding data A = Num Int | Fun FunWithAttribute and writing an instance Show FunWithAttribute. Is the additional data type avoidable?
Instances are defined for types as a whole, not individual constructors, which is why it complains about Fun not being a type.
I assume your overall goal is to have a Show instance for A, which can't be derived because functions can't (in general) have a Show instance. You have a couple options here:
Write your own Show instance outright:
That is, something like:
instance Show A where
show (Num n) = "Num " ++ show n
show (Fun _ s) = s
In many cases, this makes the most sense. But sometimes it's nicer to derive Show, especially on complex recursive types where only one case of many is not automatically Show-able.
Make A derivable:
You can only derive Show for types that contain types that themselves have Show instances. There's no instance for A -> A, so deriving doesn't work. But you can write one that uses a placeholder of some sort:
instance Show (A -> A) where
show _ = "(A -> A)"
Or even just an empty string, if you prefer.
Note that this requires the FlexibleInstances language extension; it's one of the most harmless and commonly used extensions, is supported by multiple Haskell implementations, and the restrictions it relaxes are (in my opinion) a bit silly to begin with, so there's little reason to avoid it.
An alternate approach would be to have a wrapper type, as you mention in the question. You could even make this more generic:
data ShowAs a = ShowAs a String
instance Show (ShowAs a) where
show (ShowAs _ s) = s
...and then use (ShowAs (A -> A)) in the Fun constructor. This makes it a bit awkward by forcing you to do extra pattern matching any time you want to use the wrapped type, but it gives you lots of flexibility to "tag" stuff with how it should be displayed, e.g. showId = id `ShowAs` "id" or suchlike.
Perhaps I'm not following what you are asking for. But the above code could be written like this in order to compile:
data A = Num Int
| Fun (A -> A) String
instance Show A where
show (Fun f s) = s
show (Num i) = show i
Some explanation
It looked like you were trying to write a show instance for a constructor (Fun). Class instances are written for the entire data type (there might be exceptions, dunno). So you need to write one show matching on each constructor as part of the instance. Num and Fun are each constructors of the data type A.
Also, deriving can't be used unless each parameter of each constructor is, in turn, member of, in this case, Show. Now, your example is a bit special since it wants to Show (A -> A). How to show a function is somewhat explained in the other responses, although I don't think there is an exhaustive way. The other examples really just "show" the type or some place holder.
A Show instance (or any class instance) needs to be defined for a data type, not for a type constructor. That is, you need simply
instance Show A where
Apparently, you're trying to get this instance with the deriving, but that doesn't work because Haskell doesn't know how to show A->A. Now it seems you don't even want to show that function, but deriving Show instances always show all available information, so you can't use that.
The obvious, and best, solution to your problem is worldsayshi's: don't use deriving at all, but define a proper instance yourself. Alternatively, you can define a pseudo-instance for A->A and then use deriving:
{-# LANGUAGE FlexibleInstances #-}
data A = Num Int | Fun (A->A) String deriving(Show)
instance Show (A->A) where show _ = ""
This works like
Prelude> Fun (const $ Num 3) "bla"
Fun "bla"

overload show for list

I want a newline-separated representation instead of the usual comma separated one, for may new data tyepe:
newtype SimpleRecord = SimpleRecord ([Char], [Char], Integer)
deriving (Show)
I tried to write this istance of Show class :
instance Show [SimpleRecord] where
show [(SimpleRecord (n, i, c))] = show (SimpleRecord (n, i, c))++['\n']
show (l:ls) = (show l)++['\n']++(show ls)
GHC heavily insults me.
Can someone try to explain me what can I do?
First, the Show class is supposed to be for producing Haskell source code, which the Read class can then read back in. It isn't supposed to be for producing human-readable, "pretty" output.
Having just said that, almost everyone misuses it for the latter, and it can be helpful for debugging purposes.
So, your options are:
Write some function not called show which does what you want. (As per AndrewC's comment.)
Use the showList method.
If you write deriving Show, this tells the compiler to write all the Show methods for you. If you want to write them yourself, you need to take away the deriving bit first. Then you can write your instance, which is going to look something like
instance Show SimpleRecord where
show (SimpleRecord (x, y, z)) = ...
showList rs = unlines (map show rs)
As an aside, if you didn't already know this, you can write
mapM_ print records
at the GHCi prompt to print out any list of printable things with one element per line.
As a final asside, why
newtype SimpleRecord = SimpleRecord ([Char], [Char], Integer)
rather than
data SimpleRecord = SimpleRecord [Char] [Char] Integer
Your question is quite ambiguos. If I interpret correctly you are trying to change the default Show instance for [SimpleRecord].
As GHC has already defined the instance Show [a] when Show a is defined. You get following error (after including FlexibleInstances extension) when you try to again define instance for Show [SimpleRecord].
Matching instances:
instance Show a => Show [a] -- Defined in `GHC.Show'
instance Show [SimpleRecord] -- Defined at show.hs:5:11
So you need to use OverlappingInstances language extension to allow overloading it.
It states GHC to match the most specific instance.
You might also want to include FlexibleInstances extension, which allows to mention arbitrary nested types in instance declaration..
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
newtype SimpleRecord = SimpleRecord ([Char], [Char], Integer)
deriving (Show)
instance Show [SimpleRecord] where
show [SimpleRecord (n, i, c)] = show (SimpleRecord (n, i, c))++"\n"
show (l:ls) = show l ++ "\n" ++ show ls
You get get more information about these language extensions at GHC Docs
Just a comment on design of your type, It is better to define your type as
data SimpleRecord = SimpleRecord String String Integer
You get more flexibility here in terms of partial constructor application etc.
I might have been missing something, but it wasn't clear why you were newtyping (String,String,Integer) rather than what you were concerned to show nicely, namely lists of them. Then you would evade the universal Show instance for lists:
newtype SimpleRecords = SimpleRecords [(String, String, Integer)]
instance Show SimpleRecords where
show (SimpleRecords []) = ""
show (SimpleRecords ((n, i, c): xs)) =
show (n, i, c) ++ "\n" ++ show (SimpleRecords xs)
-- Prelude Main> let a = words "We hold these truths to be self-evident"
-- Prelude Main> let b = words "All the best people are using Clorox"
-- Prelude Main> let c = zip3 a b [1::Integer ..]
-- Prelude Main> SimpleRecords c
-- ("We","All",1)
-- ("hold","the",2)
-- ("these","best",3)
-- ("truths","people",4)
-- ("to","are",5)
-- ("be","using",6)
-- ("self-evident","Clorox",7)

Resources