Can there be a special Show instance for a tuple? - haskell

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.

Related

Haskell instance: how could this be some valid code?

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.

When it's a String use "id", otherwise use "show"

I have the following piece of code
data Showable = forall a . (Show a) => Showable a
instance Show Showable where
show (Showable a) =
show a
It works quite fine:
> show (Showable 1)
"1"
> show (Showable True)
"True"
But when it's a string, I get unwanted quotes:
> show (Showable "foo")
"\"foo\""
I know it's because of apply show over a string, so it's the same as:
> show "foo"
"\"foo\""
What I want to do, is when it's a String, use id instead of show.
Something like:
instance Show Showable where
show (Showable a) =
case a of
(String _) -> id a
_ -> show a
Is it possible? Any workarounds?
It is possible to do something along these lines but you need some boilerplate unfortunately, so it would probably be better to go about it in a different way.
Here is one way it could be done though (using something equivalent to a dependent sum):
{-# LANGUAGE ExistentialQuantification, GADTs, DataKinds, TypeFamilies #-}
type family StringP a where
StringP String = 'True
StringP a = 'False
data CheckStringness a where
IsTypeString :: CheckStringness String
NotTypeString :: (StringP a) ~ 'False => CheckStringness a
data Showable = forall a. Show a => Showable (CheckStringness a) a
instance Show Showable where
show (Showable IsTypeString str ) = str
show (Showable NotTypeString other) = show other
The difficult part is that you cannot directly reflect a type into a value in the way that you would want to for this, so you have to write a bit of boilerplate code to take care of that.
Example usage:
ghci> show (Showable NotTypeString (123 :: Int))
"123"
ghci> show (Showable NotTypeString ())
"()"
ghci> show (Showable IsTypeString "abc")
"abc"
Like I said though, I would try to approach the problem in a different way entirely (such as Luis Casillas's and ErikR's recommendations in the comments on this question), to avoid being in this situation in this first place. The main reason I demonstrated this is that things similar to this technique may at some point become nicer to work with and have more practical value than they do now, especially as the dependent Haskell initiative continues.
I don't know how to do this, but I'm pretty sure this requires some Haskell extensions. First, there is the equality constraint, like (a ~ String). The ~ notation is explained in this article: http://chrisdone.com/posts/haskell-constraint-trick
Also, there is overlapping instances: https://wiki.haskell.org/GHC/AdvancedOverlap
Here is what I would do (untested code, unlikely to compile):
class Show1 a where
show1 :: a -> String
-- requires some extension since String = [Char]
instance (a ~ String) => Show1 a where
show1 = id
instance Show a => Show1 a where
show1 a = show a
instance Show Showable where
show (Showable a) = show1 a

Haskell show pair of string

How can I define an instance for showing (String, String) structure
instance Show (String, String) where
show (a, b) = show a ++ show b
Thanks!
The short answer is that you can't without a bunch of language extensions that really are better suited to other tasks.
There is already an instance for (Show a, Show b) => Show (a, b), meaning that defining it for (String, String) would overlap with the already existing one. A better choice would be to write your own showStrTuple as
showStrTuple :: (String, String) -> String
showStrTuple (a, b) = show a ++ show b
Alternatively, if you really want to use show on it, make a newtype (which are designed for defining new typeclasses that would otherwise conflict with existing ones):
newtype StrTuple = StrTuple { unStrTuple :: (String, String) } deriving (Eq)
instance Show StrTuple where
show (StrTuple (a, b)) = show a ++ show b
Then you just construct it with
show $ StrTuple ("hello", "world")
If you'd used proper indentation, and switched on the altogether harmless -XFlexibleInstances
{-# LANGUAGE FlexibleInstances #-}
instance Show (String, String) where
show (a, b) = show a ++ show b
then this instance would, in itself, work (you need to switch on -XFlexibleInstances). However, it won't compile because a strictly more general instance
instance (Show a, Show b) => Show (a, b) where
show (a, b) = "(" ++ show a ++ "," ++ show b ++ ")"
is already defined in the prelude. If you're determined to override that one then you also need to switch on -XOverlappingInstances. But this one is not so harmless; in fact it's evil: overlapping instances can lead to all kinds of trouble, and for your specific definition the instance also doesn't comply with the requirement that read . show ≡ id.

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)

Haskell Existential Types

I'm trying to wrap my brain around Haskell's existential types, and my first example is a heterogeneous list of things that can be shown:
{-# LANGUAGE ExistentialQuantification #-}
data Showable = forall a. Show a => Showable a
showableList :: [Showable]
showableList = [Showable "frodo", Showable 1]
Now it seems to me that the next thing I would want to do is make Showable an instance of Show so that, for example, my showableList could be displayed in the repl:
instance Show Showable where
show a = ...
The problem I am having is that what I really want to do here is call the a's underlying show implementation. But I'm having trouble referring to it:
instance Show Showable where
show a = show a
picks out Showable's show method on the RHS which runs in circles. I tried auto-deriving Show, but that doesn't work:
data Showable = forall a. Show a => Showable a
deriving Show
gives me:
Can't make a derived instance of `Show Showable':
Constructor `Showable' does not have a Haskell-98 type
Possible fix: use a standalone deriving declaration instead
In the data type declaration for `Showable'
I'm looking for someway to call the underlying Show::show implementation so that Showable does not have to reinvent the wheel.
instance Show Showable where
show (Showable a) = show a
show a = show a doesn't work as you realized because it recurses infinitely. If we try this without existential types we can see the same problem and solution
data D = D Int
instance Show D where show a = show a -- obviously not going to work
instance Show D where show (D a) = "D " ++ (show a) -- we have to pull out the underlying value to work with it

Resources