overload show for list - haskell

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)

Related

Error matching types: using MultiParamTypeClasses and FunctionalDependencies to define heterogeneous lists and a function that returns first element

There is a relevant question concerning Functional Dependencies used with GADTs. It turns out that the problem is not using those two together, since similar problems arise without the use of GADTs. The question is not definitively answered, and there is a debate in the comments.
The problem
I am trying to make a heterogeneous list type which contains its length in the type (sort of like a tuple), and I am having a compiling error when I define the function "first" that returns the first element of the list (code below). I do not understand what it could be, since the tests I have done have the expected outcomes.
I am a mathematician, and a beginner to programming and Haskell.
The code
I am using the following language extensions:
{-# LANGUAGE GADTs, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}
First, I defined natural numbers in the type level:
data Zero = Zero
newtype S n = S n
class TInt i
instance TInt Zero
instance (TInt i) => TInt (S i)
Then, I defined a heterogeneous list type, along with a type class that provides the type of the first element:
data HList a as where
EmptyList :: HList a as
HLCons :: a -> HList b bs -> HList a (HList b bs)
class First list a | list -> a
instance First (HList a as) a
And finally, I defined the Tuple type:
data Tuple list length where
EmptyTuple :: Tuple a Zero
TCons :: (TInt length) => a -> Tuple list length -> Tuple (HList a list) (S length)
I wanted to have the function:
first :: (First list a) => Tuple list length -> a
first EmptyTuple = error "first: empty Tuple"
first (TCons x _) = x
but it does not compile, with a long error that appears to be that it cannot match the type of x with a.
Could not deduce: a1 ~ a
from the context: (list ~ HList a1 list1, length ~ S length1,
TInt length1)
bound by a pattern with constructor:
TCons :: forall length a list.
TInt length =>
a -> Tuple list length -> Tuple (HList a list) (S length),
in an equation for ‘first’
[...]
Relevant bindings include
x :: a1 (bound at problem.hs:26:14)
first :: Tuple list length -> a (bound at problem.hs:25:1)
The testing
I have tested the type class First by defining:
testFirst :: (First list a) => Tuple list length -> a
testFirst = undefined
and checking the type of (testFirst x). For example:
ghci> x = TCons 'a' (TCons 5 (TCons "lalala" EmptyTuple))
ghci> :t (testFirst x)
(testFirst x) :: Char
Also this works as you would expect:
testMatching :: (Tuple (HList a as) n) -> a
testMatching (TCons x _) = x
"first" is basically these two combined.
The question
Am I attempting to do something the language does not support (maybe?), or have I stumbled on a bug (unlikely), or something else (most likely)?
Oh dear, oh dear. You have got yourself in a tangle. I imagine you've had to battle through several perplexing error messages to get this far. For a (non-mathematician) programmer, there would have been several alarm bells hinting it shouldn't be this complicated. I'll 'patch up' what you've got now; then try to unwind some of the iffy code.
The correction is a one-line change. The signature for first s/b:
first :: Tuple (HList a as) length -> a
As you figured out in your testing. Your testFirst only appeared to make the right inference because the equation didn't try to probe inside a GADT. So no, that's not comparable.
There's a code 'smell' (as us humble coders call it): your class First has only one instance -- and I can't see any reason it would have more than one. So just throw it away. All I've done with the signature for first is put the list's type from the First instance head direct into the signature.
Explanation
Suppose you wrote the equations for first without giving a signature. That gets rejected blah rigid type variable bound by a pattern with constructor ... blah. Yes GHC's error messages are completely baffling. What it means is that the LHS of first's equations pattern match on a GADT constructor -- TCons, and any constraints/types bound into it cannot 'escape' the pattern match.
We need to expose the types inside TCons in order to let the type pattern-matched to variable x escape. So TCons isn't binding just any old list; it's specifically binding something of the form (HList a as).
Your class First and its functional dependency was attempting to drive that typing inside the pattern match. But GADTs have been maliciously designed to not co-operate with FunDeps, so that just doesn't work. (Search SO for '[haskell] functional dependency GADT' if you want to be more baffled.)
What would work is putting an Associated Type inside class First; or building a stand-alone 'type family'. But I'm going to avoid leading a novice into advanced features.
Type Tuple not needed
As #JonPurdy points out, the 'spine' of your HList type -- that is, the nesting of HLConss is doing just the same job as the 'spine' of your TInt data structure -- that is, the nesting of Ss. If you want to know the length of an HList, just count the number of HLCons.
So also throw away Tuple and TInt and all that gubbins. Write first to apply to an HList. (Then it's a useful exercise to write a length-indexed access: nth element of an HList -- not forgetting to fail gracefully if the index points beyond its end.)
I'd avoid the advanced features #Jon talks about, until you've got your arms around GADTs. (It's perfectly possible to program over heterogeneous lists without using GADTs -- as did the pioneers around 2003, but I won't take you backwards.)
I was trying to figure out how to do "calculations" on the type level, there are more things I'd like to implement.
Ok ... My earlier answer was trying to make minimal changes to get your code going. There's quite a bit of duplication/unnecessary baggage in your O.P. In particular:
Both HList and Tuple have constructors for empty lists (also length Zero means empty list). Furthermore both those Emptys allege there's a type (variable) for the head and the tail of those empty (non-)lists.
Because you've used constructors to denote empty, you can't catch at the type level attempts to extract the first of an empty list. You've ended up with a partial function that calls error at run time. Better is to be able to trap first of an empty list at compile time, by rejecting the program.
You want to experiment with FunDeps for obtaining the type of the first (and presumably other elements). Ok then to be type-safe, prevent there being an instance of the class that alleges the non-existent head of an empty has some type.
I still want to have the length as part of the type, it is the whole point of my type.
Then let's express that more directly (I'll use fresh names here, to avoid clashes with your existing code.) (I'm going to need some further extensions, I'll explain those at the end.):
data HTuple list length where
MkHTuple :: (HHList list, TInt length) => list -> length -> HTuple list length
This is a GADT with a single constructor to pair the list with its length. TInt length and types Zero, S n are as you have already. With HHList I've followed a similar structure.
data HNil = HNil deriving (Eq, Show)
data HCons a as = HCons a as deriving (Eq, Show)
class HHList l
instance HHList HNil
instance HHList (HCons a as)
class (HHList list) => HFirst list a | list -> a where hfirst :: list -> a
-- no instance HFirst HNil -- then attempts to call hfirst will be type error
instance HFirst (HCons a as) a where hfirst (HCons x xs) = x
HNil, HCons are regular datatypes, so we can derive useful classes for them. Class HHList groups the two datatypes, as you've done with TInt.
HFirst with its FunDep for the head of an HHList then works smoothly. And no instance HFirst HNil because HNil doesn't have a first. Note that HFirst has a superclass constraint (HHList list) =>, saying that HFirst applies only for HHLists.
We'd like HTuple to be Eqable and Showable. Because it's a GADT, we must go a little around the houses:
{-# LANGUAGE StandaloneDeriving #-}
deriving instance (Eq list, Eq length) => Eq (HTuple list length)
deriving instance (Show list, Show length) => Show (HTuple list length)
Here's a couple of sample tuples; and a function to get the first element, going via the HFirst class and its method:
htEmpty = MkHTuple HNil Zero
htup1 = MkHTuple (HCons (1 :: Int) HNil) (S Zero)
tfirst :: (HFirst list a) => HTuple list length -> a -- using the FunDep
tfirst (MkHTuple list length) = hfirst list
-- > :set -XFlexibleContexts -- need this in your session
-- > tfirst htup1 ===> 1
-- > tfirst htEmpty ===> error: No instance for (HFirst HNil ...
But you don't want to be building tuples with all those explicit constructors. Ok, we could define a cons-like function:
thCons x (MkHTuple li le) = MkHTuple (HCons x li) (S le)
htup2 = thCons "Two" htup1
But that doesn't look like a constructor. Furthermore you really (I suspect) want something to both construct and destruct (pattern-match) a tuple into a head and a tail. Then welcome to PatternSynonyms (and I'm afraid quite a bit of ugly declaration syntax, so the rest of your code can be beautiful). I'll put the beautiful bits first: THCons looks just like a constructor; you can nest multiple calls; you can pattern match to get the first element.
htupA = THCons 'A' THEmpty
htup3 = THCons True $ THCons "bB" $ htupA
htfirst (THCons x xs) = x
-- > htfirst htup3 ===> True
{-# LANGUAGE PatternSynonyms, ViewPatterns, LambdaCase #-}
pattern THEmpty = MkHTuple HNil Zero -- simple pattern, spelled upper-case like a constructor
-- now the ugly
pattern THCons :: (HHList list, TInt length)
=> a -> HTuple list length -> HTuple (HCons a list) (S length)
pattern THCons x tup <- ((\case
{ (MkHTuple (HCons x li) (S le) )
-> (x, (MkHTuple li le)) } )
-> (x, tup) )
where
THCons x (MkHTuple li le) = MkHTuple (HCons x li) (S le)
Look first at the last line (below the where) -- it's just the same as for function thCons, but spelled upper case. The signature (two lines starting pattern THCons ::) is as inferred for thCons; but with explicit class constraints -- to make sure we can build a HTuple only from valid components; which we need to have guaranteed when deconstructing the tuple to get its head and a properly formed tuple for the rest -- which is all that ugly code in the middle.
Question to the floor: can that pattern decl be made less ugly?
I won't try to explain the ugly code; read ViewPatterns in the User Guide. That's the last -> just above the where.

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

Set specific properties for data in Haskell

Let us say I want to make a ADT as follows in Haskell:
data Properties = Property String [String]
deriving (Show,Eq)
I want to know if it is possible to give the second list a bounded and enumerated property? Basically the first element of the list will be the minBound and the last element will be the maxBound. I am trying,
data Properties a = Property String [a]
deriving (Show, Eq)
instance Bounded (Properties a) where
minBound a = head a
maxBound a = (head . reverse) a
But not having much luck.
Well no, you can't do quite what you're asking, but maybe you'll find inspiration in this other neat trick.
{-# language ScopedTypeVariables, FlexibleContexts, UndecidableInstances #-}
import Data.Reflection -- from the reflection package
import qualified Data.List.NonEmpty as NE
import Data.List.NonEmpty (NonEmpty (..))
import Data.Proxy
-- Just the plain string part
newtype Pstring p = P String deriving Eq
-- Those properties you're interested in. It will
-- only be possible to produce bounds if there's at
-- least one property, so NonEmpty makes more sense
-- than [].
type Props = NonEmpty String
-- This is just to make a Show instance that does
-- what you seem to want easier to write. It's not really
-- necessary.
data Properties = Property String [String] deriving Show
Now we get to the key part, where we use reflection to produce class instances that can depend on run-time values. Roughly speaking, you can think of
Reifies x t => ...
as being a class-level version of
\(x :: t) -> ...
Because it operates at the class level, you can use it to parametrize instances. Since Reifies x t binds a type variable x, rather than a term variable, you need to use reflect to actually get the value back. If you happen to have a value on hand whose type ends in p, then you can just apply reflect to that value. Otherwise, you can always magic up a Proxy :: Proxy p to do the job.
-- If some Props are "in the air" tied to the type p,
-- then we can show them along with the string.
instance Reifies p Props => Show (Pstring p) where
showsPrec k p#(P str) =
showsPrec k $ Property str (NE.toList $ reflect p)
-- If some Props are "in the air" tied to the type p,
-- then we can give Pstring p a Bounded instance.
instance Reifies p Props => Bounded (Pstring p) where
minBound = P $ NE.head (reflect (Proxy :: Proxy p))
maxBound = P $ NE.last (reflect (Proxy :: Proxy p))
Now we need to have a way to actually bind types that can be passed to the type-level lambdas. This is done using the reify function. So let's throw some Props into the air and then let the butterfly nets get them back.
main :: IO ()
main = reify ("Hi" :| ["how", "are", "you"]) $
\(_ :: Proxy p) -> do
print (minBound :: Pstring p)
print (maxBound :: Pstring p)
./dfeuer#squirrel:~/src> ./WeirdBounded
Property "Hi" ["Hi","how","are","you"]
Property "you" ["Hi","how","are","you"]
You can think of reify x $ \(p :: Proxy p) -> ... as binding a type p to the value x; you can then pass the type p where you like by constraining things to have types involving p.
If you're just doing a couple of things, all this machinery is way more than necessary. Where it gets nice is when you're performing lots of operations with values that have phantom types carrying extra information. In many cases, you can avoid most of the explicit applications of reflect and the explicit proxy handling, because type inference just takes care of it all for you. For a good example of this technique in action, see the hyperloglog package. Configuration information for the HyperLogLog data structure is carried in a type parameter; this guarantees, at compile time, that only similarly configured structures are merged with each other.

Is there a polymorphic `toString` function that doesn't add quotes?

In most OO languages that I'm familiar with, the toString method of a String is actually just the identity function. But in Haskell show adds double quotes.
So if I write a function something like this
f :: Show a => [a] -> String
f = concat . map show
it works as expected for numbers
f [0,1,2,3] -- "0123"
but Strings end up with extra quotes
f ["one", "two", "three"] -- "\"one\"\"two\"\"three\""
when I really want "onetwothree".
If I wanted to write f polymorphically, is there a way to do it with only a Show constraint, and without overriding the Show instance for String (if that's even possible).
The best I can come up with is to create my own type class:
class (Show a) => ToString a where
toString = show
and add an instance for everything?
instance ToString String where toString = id
instance ToString Char where toString = pure
instance ToString Int
instance ToString Maybe
...etc
I think the root cause of your problem is that show isn't really renderToText. It's supposed to produce text that you could paste into Haskell code to get the same value, or convert back to the same value using read.
For that purpose, show "foo" = "foo" wouldn't work, because show "1" = "1" and show 1 = "1", which loses information.
The operation you want to be able to apply to "foo" to get "foo" and to 1 to get "1" is something other than show. show just isn't a Java-esque toString.
When I've needed this before, I have indeed made my own new type class and made a bunch of things instances of it, and then used that rather than Show. Most of the instances were implemented with show, but String wasn't the only one I wanted to customise so the separate type class wasn't completely wasted. In practice, I found there were only a handful of types that I actually needed the instance for, and it was pretty trivial to add them as I got compile errors.
The Pretty class and its corresponding type Doc have the needed behavior for Show. Your link shows a different use case, however; maybe you could edit the question?
You could do this:
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
class Show a => ToString a where
toString :: a -> String
instance Show a => ToString a where
toString = show
instance ToString String where
toString = id
Prelude> toString "hello"
"hello"
Prelude> toString 3
"3"
Note that this is probably a terrible idea.
You could use newtype with OverloadedStrings:
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
newtype LiteralString = LS ByteString
instance IsString LiteralString where fromString = LS . B.pack
instance Show LiteralString where show (LS x) = B.unpack x
instance Read LiteralString where readsPrec p s = map (\(!s, !r) -> (LS s,r)) $! readsPrec p s
hello :: LiteralString
hello = "hello world"
main :: IO ()
main = putStrLn . show $! hello
output:
hello world
The double quotes in the normal case are actually useful when reading a shown string back in the context of larger expression as they clearly delimit shown string values from values of other shown types:
x :: (ByteString, Int)
x = read . show $! ("go", 10)
-- string value starts --^^-- ends
y :: (LiteralString, Int)
y = read . show $! ("go", 10)
-- string value starts --^ ^ consumes all characters; read fails

How do I implement this function without using mixed lists?

Let's say I have a function that takes a list of function-list pairs, and maps the function in each pair onto the list in the pair, for example:
myFunction [("SOME"++,["DAY","ONE"]), (show,[1,2])] == [["SOMEDAY", "SOMEONE"],["1","2"]]
Is there a way of implementing myFunction so that the code I provided above will work as is without any modifications?
My problem is I can't figure out how to implement myFunction because the types of each sub-list could be different (in my example I have a list of strings ["DAY", ONE"], and a list of numbers: [1,2]). I know that each function in the list will convert its list into a list of strings (so the final list will have type [[Char]]), but I don't know how to express this in Haskell.
You can do it with existential types
{-# LANGUAGE ExistentialQuantification #-}
data T = forall a b. Show b => (:?:) (a -> b) [a]
table =
[ ("SOME"++) :?: ["DAY","ONE"]
, (show) :?: [1,2]
, (+1) :?: [2.9, pi]
]
And run it as:
apply :: T -> String
apply (f :?: xs) = show $ map f xs
main = print $ map apply table
You want to use existential quantification to define a type that can hold any value as long as it is a member of the Show typeclass. For example:
{-# LANGUAGE ExistentialQuantification #-}
data S = forall a. Show a => S a
instance Show S where
show (S s) = show s
f :: [S] -> [String]
f xs = map show xs
And now in ghci:
*Main> f [S 1, S True, S 'c']
["1","True","'c'"]
You won't be able to run the code in your question without modification, because it contains a heterogeneous list, which the Haskell type system forbids. Instead you can wrap heterogeneous types up as a variant type (if you know in advance all the types that will be required) or as an existentially quantified type (if you don't know what types will be required, but you do know a property that they must satisfy).

Resources