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.
Related
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
This question already has answers here:
What does => mean in a type signature?
(3 answers)
Closed 7 years ago.
I've just started reading through Learn You a Haskell for Great Good. In chapter 3, I've seen the author use => but I could not find out exactly what it does and why they use it.
I think this is the first time it was used:
lucky :: (Integral a) => a -> String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry, you're out of luck, pal!"
Here is another example:
tell :: (Show a) => [a] -> String
tell [] = "The list is empty"
tell (x:[]) = "The list has one element: " ++ show x
tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y
tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y
Thanks.
In short:
Although not complete, if you haven't yet read about classes, you can see it as a constraint that there is defined a set of functions on the type a.
Explanation:
You can see it as putting constraints on a type. For instance in the case of lucky:
lucky :: (Integral a) => a -> String
It means the function is defined for any type a, as long as a is an instance of Integral.
Now I don't know if you are familiar with classes yet (those are not the ones used in object-oriented programming), but classes more or less introduce functions on a that can then by used in your function definition. For instance the class Integral is defined as:
class (Real a, Enum a) => Integral a where
quot :: a -> a -> a
rem :: a -> a -> a
div :: a -> a -> a
mod :: a -> a -> a
quotRem :: a -> a -> (a, a)
divMod :: a -> a -> (a, a)
toInteger :: a -> Integer
Now this class is rather hard to understand since it uses => in the signature as well. Perhaps an easier one is Show:
class Show a where
showsPrec :: Int -> a -> ShowS
show :: a -> String
showList :: [a] -> ShowS
It means that if a is an instance of Show, that you can use the show function on a. Otherwise the following line:
tell (x:[]) = "The list has one element: " ++ show x
would not compile since Haskell isn't sure it can call show on x. By constraining the type a however, we know that we can only use tell on types where a is an instance of Show, and thus the show function is defined.
It constrains a parameter a to a certain class, in this case Integral and 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
I know this question has been asked and answered lots of times but I still don't really understand why putting constraints on a data type is a bad thing.
For example, let's take Data.Map k a. All of the useful functions involving a Map need an Ord k constraint. So there is an implicit constraint on the definition of Data.Map. Why is it better to keep it implicit instead of letting the compiler and programmers know that Data.Map needs an orderable key.
Also, specifying a final type in a type declaration is something common, and one can see it as a way of "super" constraining a data type.
For example, I can write
data User = User { name :: String }
and that's acceptable. However is that not a constrained version of
data User' s = User' { name :: s }
After all 99% of the functions I'll write for the User type don't need a String and the few which will would probably only need s to be IsString and Show.
So, why is the lax version of User considered bad:
data (IsString s, Show s, ...) => User'' { name :: s }
while both User and User' are considered good?
I'm asking this, because lots of the time, I feel I'm unnecessarily narrowing my data (or even function) definitions, just to not have to propagate constraints.
Update
As far as I understand, data type constraints only apply to the constructor and don't propagate. So my question is then, why do data type constraints not work as expected (and propagate)? It's an extension anyway, so why not have a new extension doing data properly, if it was considered useful by the community?
TL;DR:
Use GADTs to provide implicit data contexts.
Don't use any kind of data constraint if you could do with Functor instances etc.
Map's too old to change to a GADT anyway.
Scroll to the bottom if you want to see the User implementation with GADTs
Let's use a case study of a Bag where all we care about is how many times something is in it. (Like an unordered sequence. We nearly always need an Eq constraint to do anything useful with it.
I'll use the inefficient list implementation so as not to muddy the waters over the Data.Map issue.
GADTs - the solution to the data constraint "problem"
The easy way to do what you're after is to use a GADT:
Notice below how the Eq constraint not only forces you to use types with an Eq instance when making GADTBags, it provides that instance implicitly wherever the GADTBag constructor appears. That's why count doesn't need an Eq context, whereas countV2 does - it doesn't use the constructor:
{-# LANGUAGE GADTs #-}
data GADTBag a where
GADTBag :: Eq a => [a] -> GADTBag a
unGADTBag (GADTBag xs) = xs
instance Show a => Show (GADTBag a) where
showsPrec i (GADTBag xs) = showParen (i>9) (("GADTBag " ++ show xs) ++)
count :: a -> GADTBag a -> Int -- no Eq here
count a (GADTBag xs) = length.filter (==a) $ xs -- but == here
countV2 a = length.filter (==a).unGADTBag
size :: GADTBag a -> Int
size (GADTBag xs) = length xs
ghci> count 'l' (GADTBag "Hello")
2
ghci> :t countV2
countV2 :: Eq a => a -> GADTBag a -> Int
Now we didn't need the Eq constraint when we found the total size of the bag, but it didn't clutter up our definition anyway. (We could have used size = length . unGADTBag just as well.)
Now lets make a functor:
instance Functor GADTBag where
fmap f (GADTBag xs) = GADTBag (map f xs)
oops!
DataConstraints_so.lhs:49:30:
Could not deduce (Eq b) arising from a use of `GADTBag'
from the context (Eq a)
That's unfixable (with the standard Functor class) because I can't restrict the type of fmap, but need to for the new list.
Data Constraint version
Can we do as you asked? Well, yes, except that you have to keep repeating the Eq constraint wherever you use the constructor:
{-# LANGUAGE DatatypeContexts #-}
data Eq a => EqBag a = EqBag {unEqBag :: [a]}
deriving Show
count' a (EqBag xs) = length.filter (==a) $ xs
size' (EqBag xs) = length xs -- Note: doesn't use (==) at all
Let's go to ghci to find out some less pretty things:
ghci> :so DataConstraints
DataConstraints_so.lhs:1:19: Warning:
-XDatatypeContexts is deprecated: It was widely considered a misfeature,
and has been removed from the Haskell language.
[1 of 1] Compiling Main ( DataConstraints_so.lhs, interpreted )
Ok, modules loaded: Main.
ghci> :t count
count :: a -> GADTBag a -> Int
ghci> :t count'
count' :: Eq a => a -> EqBag a -> Int
ghci> :t size
size :: GADTBag a -> Int
ghci> :t size'
size' :: Eq a => EqBag a -> Int
ghci>
So our EqBag count' function requires an Eq constraint, which I think is perfectly reasonable, but our size' function also requires one, which is less pretty. This is because the type of the EqBag constructor is EqBag :: Eq a => [a] -> EqBag a, and this constraint must be added every time.
We can't make a functor here either:
instance Functor EqBag where
fmap f (EqBag xs) = EqBag (map f xs)
for exactly the same reason as with the GADTBag
Constraintless bags
data ListBag a = ListBag {unListBag :: [a]}
deriving Show
count'' a = length . filter (==a) . unListBag
size'' = length . unListBag
instance Functor ListBag where
fmap f (ListBag xs) = ListBag (map f xs)
Now the types of count'' and show'' are exactly as we expect, and we can use standard constructor classes like Functor:
ghci> :t count''
count'' :: Eq a => a -> ListBag a -> Int
ghci> :t size''
size'' :: ListBag a -> Int
ghci> fmap (Data.Char.ord) (ListBag "hello")
ListBag {unListBag = [104,101,108,108,111]}
ghci>
Comparison and conclusions
The GADTs version automagically propogates the Eq constraint everywhere the constructor is used. The type checker can rely on there being an Eq instance, because you can't use the constructor for a non-Eq type.
The DatatypeContexts version forces the programmer to manually propogate the Eq constraint, which is fine by me if you want it, but is deprecated because it doesn't give you anything more than the GADT one does and was seen by many as pointless and annoying.
The unconstrained version is good because it doesn't prevent you from making Functor, Monad etc instances. The constraints are written exactly when they're needed, no more or less. Data.Map uses the unconstrained version partly because unconstrained is generally seen as most flexible, but also partly because it predates GADTs by some margin, and there needs to be a compelling reason to potentially break existing code.
What about your excellent User example?
I think that's a great example of a one-purpose data type that benefits from a constraint on the type, and I'd advise you to use a GADT to implement it.
(That said, sometimes I have a one-purpose data type and end up making it unconstrainedly polymorphic just because I love to use Functor (and Applicative), and would rather use fmap than mapBag because I feel it's clearer.)
{-# LANGUAGE GADTs #-}
import Data.String
data User s where
User :: (IsString s, Show s) => s -> User s
name :: User s -> s
name (User s) = s
instance Show (User s) where -- cool, no Show context
showsPrec i (User s) = showParen (i>9) (("User " ++ show s) ++)
instance (IsString s, Show s) => IsString (User s) where
fromString = User . fromString
Notice since fromString does construct a value of type User a, we need the context explicitly. After all, we composed with the constructor User :: (IsString s, Show s) => s -> User s. The User constructor removes the need for an explicit context when we pattern match (destruct), becuase it already enforced the constraint when we used it as a constructor.
We didn't need the Show context in the Show instance because we used (User s) on the left hand side in a pattern match.
Constraints
The problem is that constraints are not a property of the data type, but of the algorithm/function that operates on them. Different functions might need different and unique constraints.
A Box example
As an example, let's assume we want to create a container called Box which contains only 2 values.
data Box a = Box a a
We want it to:
be showable
allow the sorting of the two elements via sort
Does it make sense to apply the constraint of both Ord and Show on the data type? No, because the data type in itself could be only shown or only sorted and therefore the constraints are related to its use, not it's definition.
instance (Show a) => Show (Box a) where
show (Box a b) = concat ["'", show a, ", ", show b, "'"]
instance (Ord a) => Ord (Box a) where
compare (Box a b) (Box c d) =
let ca = compare a c
cb = compare b d
in if ca /= EQ then ca else cb
The Data.Map case
Data.Map's Ord constraints on the type is really needed only when we have > 1 elements in the container. Otherwise the container is usable even without an Ord key. For example, this algorithm:
transf :: Map NonOrd Int -> Map NonOrd Int
transf x =
if Map.null x
then Map.singleton NonOrdA 1
else x
Live demo
works just fine without the Ord constraint and always produce a non empty map.
Using DataTypeContexts reduces the number of programs you can write. If most of those illegal programs are nonsense, you might say it's worth the runtime cost associated with ghc passing in a type class dictionary that isn't used. For example, if we had
data Ord k => MapDTC k a
then #jefffrey's transf is rejected. But we should probably have transf _ = return (NonOrdA, 1) instead.
In some sense the context is documentation that says "every Map must have ordered keys". If you look at all of the functions in Data.Map you'll get a similar conclusion "every useful Map has ordered keys". While you can create maps with unordered keys using
mapKeysMonotonic :: (k1 -> k2) -> Map k1 a -> Map k2 a
singleton :: k2 a -> Map k2 a
But the moment you try to do anything useful with them, you'll wind up with No instance for Ord k2 somewhat later.
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.