How do you customize the Show instance for a Haskell record? - haskell

I have a Haskell record data type that looks like this:
data Client = Client { clientId :: Int
, nickname :: Text
, clientSink :: Maybe (WS.Sink WS.Hybi00)
, clientRoom :: Maybe Room
}
I can't derive a Show instance from this because of WS.Sink has no Show instance.
How can I make a Show instance that excludes just the clientSink field, but prints the rest of the record fields like a normal record?
Should I just create a custom Show instance for WS.Sink?

Add a Show instance for WS.Sink
instance Show WS.Sink where show a = "Sink"
or whatever dummy value you want.

I'm not sure you really want an instance of Show, in this case. From the docs.
Derived instances of Show have the following properties, which are compatible with derived instances of Read:
The result of show is a syntactically correct Haskell expression containing only constants, given the fixity declarations in force at the point where the type is declared. It contains only the constructor names defined in the data type, parentheses, and spaces. When labelled constructor fields are used, braces, commas, field names, and equal signs are also used.
This does come with the caveat that it applies only to derived instances, but I'm a stickler for contracts, and have gotten used to assuming that read . show is effectively a no-op. You'd run into this same problem again when trying to automatically derive an instance for Read of course, so it's not like you would be introducing a semantic error by using Show now, it's just a matter of preference.
Depending on your context (taking a wild guess, you're trying to debug by printing intermediate values somewhere?) defining another typeclass and implementing a toString-like function might work best for you without being potentially misleading as to the show functionality of your instance. E.g.,
class ToString a where
toString :: a -> String
instance ToString Client where
toString c = "Client {"
++ shows (clientId c) ", "
++ shows (nickname c) ", "
++ shows (isJust (clientSink c)) ", "
++ show (clientRoom c)
++ "}"
And then if you wanted to turn this into a Show instance it's as simple as
instance Show Client where
show = toString

Related

Efficient way of printing property names in Haskell

Hello i am new to Haskell and i was wondering :
For every new defined type constructor even if it is something with 0 depth eg.:
data Letter =A | B | C deriving (Show)
do i have to provide
instance Show Type
Letter A = "A"
Letter B ="B"
Letter C ="C"
I understand that for nested types you have to provide Show implementation but for something simple is there no other way to just use something equivalent to reflection (C#) ? Just get the property name / constructor name and ToString-it ?
Do haskell programmers provide instances for Show for any adhoc type they create?
By nested types i mean having a simple ADT inside another ADT inside another etc..but all you want is to get their names:
e.g:
data Person = Male | Female
data IsMarried=Yes | No
data Worker=Worker{
person::Person,
status::IsMarried
}
For this kind of nesting do i really have to define instance of Show for all these type constructors even though all i want is their name be "stringified"?
Do I have to provide [a show instance for every type?]
No, because you have automatically derived Show:
data Letter = A | B | C deriving (Show)
-- ^^^^^^^^^^^^^^^ Here
However, if you want a 'smarter' show, such as displaying a custom list as [1,2,3] rather than a mess of constructors, you're going to have to write it yourself.
You can do the same for a number of classes (Including Eq,Ord,Read,Enum, and Bounded) but most classes, including user-defined classes, must be implemented manually without the use of certain language extensions.
I understand that for nested types you have to provide Show implementation[...]
You do not! For instance, I can write this:
data Maybe a = Just a | Nothing deriving (Show)
And the compiler will automatically add the necessary constraints, despite it being a 'nested' type.
Just get the property name / constructor name and ToString-it ?
There are no 'properties' in Haskell - don't think in terms of C# here. show is the equivalent of ToString. However, a form of type reflection is available in TypeReps, though I would advise not using this until you have a solid grasp on Haskell.
Since #AJFarmar edit back his answer when i change it:
Do I have to provide [a show instance for every type?]
Yes. Either by deriving it with deriving Show, or by supplying a type instance
instance Show -type- where...
I understand that for nested types you have to provide Show implementation[...]
Yes you do, the compiler will not add any necessary instances for Show.
data Test = Test -- no instance for Show
test :: String
test = show $ (Just Test :: Maybe Test)
Will not compile with the error message:
main.hs:4:8: error:
• No instance for (Show Test) arising from a use of ‘show’
• In the expression: show $ (Just Test :: Maybe Test)
In an equation for ‘test’: test = show $ (Just Test :: Maybe Test)
Which is why you need to have a Show instance for a aswell. If one already exists, you do not have to supply a new one, however.

Why is the restriction on newtype?

I read that "newtype has exactly one constructor with exactly one field inside it." Is this restriction adds any advantage? If the value constructor is limited with only one field, why can't i use the field directly in my code, instead of wrapping it with newtype?
newtype is a tool for creating data abstraction that has no runtime cost.
What do I mean by abstraction?
Suppose you have:
greetPerson :: String -> String -> String
greetPerson greeting name = greeting ++ " " ++ name
greetPerson "Hello" "Mike" => "Hello Mike"
This works fine, but it opens opportunities for misuse:
greetPerson "Mike" "Hello" => "Mike Hello"
The problem is that you're using the same type everywhere (String), carrying no semantic meaning. Let's use a newtype:
newtype Name = Name String
greetPerson :: String -> Name -> String
greetPerson greeting (Name name) = greeting ++ " " ++ name
greetPerson "Hello" (Name "Mike") => "Hello Mike"
We end up with the same functionality, but now the type signature carries more meaning and the compiler can tell us when we misuse it.
What do I mean by no runtime cost?
The newtype from my example exists only at the type level and the compiler generates exactly the same code as if I used String throughout.
This hints at why newtype is only allowed for one constructor with one field.
Imagine you tried to make newtype work for more than one constructor. How would you distinguish which one you have at runtime? You'd have to store some additional information.
Same with more than one field. You'd need some way to bundle two fields together.
All of them add some runtime cost which newtype promises not to do.
If you want more than one field or more than one constructor simply use data:
data Foo = Bar String | Baz Int Bool

Why can't I use the type `Show a => [Something -> a]`?

I have a record type say
data Rec {
recNumber :: Int
, recName :: String
-- more fields of various types
}
And I want to write a toString function for Rec :
recToString :: Rec -> String
recToString r = intercalate "\t" $ map ($ r) fields
where fields = [show . recNumber, show . recName]
This works. fields has type [Rec -> String]. But I'm lazy and I would prefer writing
recToString r = intercalate "\t" $ map (\f -> show $ f r) fields
where fields = [recNumber, recName]
But this doesn't work. Intuitively I would say fields has type Show a => [Rec -> a] and this should be ok. But Haskell doesn't allow it.
I'd like to understand what is going on here. Would I be right if I said that in the first case I get a list of functions such that the 2 instances of show are actually not the same function, but Haskell is able to determine which is which at compile time (which is why it's ok).
[show . recNumber, show . recName]
^-- This is show in instance Show Number
^-- This is show in instance Show String
Whereas in the second case, I only have one literal use of show in the code, and that would have to refer to multiple instances, not determined at compile time ?
map (\f -> show $ f r) fields
^-- Must be both instances at the same time
Can someone help me understand this ? And also are there workarounds or type system expansions that allow this ?
The type signature doesn't say what you think it says.
This seems to be a common misunderstanding. Consider the function
foo :: Show a => Rec -> a
People frequently seem to think this means that "foo can return any type that it wants to, so long as that type supports Show". It doesn't.
What it actually means is that foo must be able to return any possible type, because the caller gets to choose what the return type should be.
A few moments' thought will reveal that foo actually cannot exist. There is no way to turn a Rec into any possible type that can ever exist. It can't be done.
People often try to do something like Show a => [a] to mean "a list of mixed types but they all have Show". That obviously doesn't work; this type actually means that the list elements can be any type, but they still have to be all the same.
What you're trying to do seems reasonable enough. Unfortunately, I think your first example is about as close as you can get. You could try using tuples and lenses to get around this. You could try using Template Haskell instead. But unless you've got a hell of a lot of fields, it's probably not even worth the effort.
The type you actually want is not:
Show a => [Rec -> a]
Any type declaration with unbound type variables has an implicit forall. The above is equivalent to:
forall a. Show a => [Rec -> a]
This isn't what you wan't, because the a must be specialized to a single type for the entire list. (By the caller, to any one type they choose, as MathematicalOrchid points out.) Because you want the a of each element in the list to be able to be instantiated differently... what you are actually seeking is an existential type.
[exists a. Show a => Rec -> a]
You are wishing for a form of subtyping that Haskell does not support very well. The above syntax is not supported at all by GHC. You can use newtypes to sort of accomplish this:
{-# LANGUAGE ExistentialQuantification #-}
newtype Showy = forall a. Show a => Showy a
fields :: [Rec -> Showy]
fields = [Showy . recNumber, Showy . recName]
But unfortunatley, that is just as tedious as converting directly to strings, isn't it?
I don't believe that lens is capable of getting around this particular weakness of the Haskell type system:
recToString :: Rec -> String
recToString r = intercalate "\t" $ toListOf (each . to fieldShown) fields
where fields = (recNumber, recName)
fieldShown f = show (f r)
-- error: Couldn't match type Int with [Char]
Suppose the fields do have the same type:
fields = [recNumber, recNumber]
Then it works, and Haskell figures out which show function instance to use at compile time; it doesn't have to look it up dynamically.
If you manually write out show each time, as in your original example, then Haskell can determine the correct instance for each call to show at compile time.
As for existentials... it depends on implementation, but presumably, the compiler cannot determine which instance to use statically, so a dynamic lookup will be used instead.
I'd like to suggest something very simple instead:
recToString r = intercalate "\t" [s recNumber, s recName]
where s f = show (f r)
All the elements of a list in Haskell must have the same type, so a list containing one Int and one String simply cannot exist. It is possible to get around this in GHC using existential types, but you probably shouldn't (this use of existentials is widely considered an anti-pattern, and it doesn't tend to perform terribly well). Another option would be to switch from a list to a tuple, and use some weird stuff from the lens package to map over both parts. It might even work.

Derive Eq and Show for type alias in Haskell

I've the following type alias
data Bindable = Const Value
| Variable Location
| Func Function
| Proc
deriving (Eq, Show)
type Function = Argument -> Store -> Value
but the compiler gives me an error
No instance for (Show Function)
arising from the 'deriving' clause of a data type declaration
Possible fix:
add an instance declaration for (Show Function)
or use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
When deriving the instance for (Show Bindable)
Can I define Show & Eq for Function? If not then what would be the solution? Should I define Eq and Show to Argument, Store and Value?
Type class instances may only be defined for "real" types, as defined by a data or newtype declaration. A type declaration is a "fake" type—just an abbreviation for a longer type.
But that's just problem #1 in this case. Problem #2 is that even if you do this...
newtype Function = Function (Argument -> Store -> Value)
...there might still be no truly useful Show instance for Function. How do turn a function into a string? There are two strategies. First, the "just give up" strategy:
instance Show Function where
show _ = "<some Function, no clue what it does>"
Second, the "canonical example" strategy, where you apply the Function to some canonical Argument and Store and show these together with the Value result:
instance Show Function where
show (Function fn) = "Function: "
++ show defaultArgument
++ " -> "
++ show defaultStore
++ " -> "
++ show (fn defaultArgument defaultStore)
The idea here is to display the Function as one particular argument/value mapping of it that might help you identify it more precisely than just using the same constant string for all of them. Whether this helps or not depends on what your functions do.
But now we have problem #3: neither of these obeys the intent/contract of the Show and Read classes, which is that read (show x) is equivalent to x. (People do often ignore this intent, however, just because they want to print something and Show is the quickest ticket. So much that, as Thomas DuBuisson points out, there's a standard module Text.Show.Functions that implements the "just give up" strategy.)
As for the Eq class, the answer is that it's just impossible in general to compare two functions for equality. (If I recall correctly, it's equivalent to solving the Halting Problem, but don't quote me on that.) If your solution requires you to compare functions for equality, you need a new solution...
Just import Text.Show.Functions. Your type is just an alias, the error message is saying it can't find an instance of Show for (->), but an instance is available in that module.
Prelude> import Text.Show.Functions
Prelude Text.Show.Functions> show (+1)
"<function>"

What is the showS trick in Haskell?

I have seen references to the showS trick to build strings (e.g., in this discussion), but I have never seen a good description of it.
What is the showS trick?
In the standard library, ShowS is defined as:
type ShowS = String -> String
This is a difference list.
The trick is that a string xs is represented as a ShowS by the function that prepends it to any other list: (xs ++). This allows efficient concatenation, avoiding the problems of nested left-associative concatenation (i.e. ((as ++ bs) ++ cs) ++ ds). For example:
hello = ("hello" ++)
world = ("world" ++)
-- We can "concatenate" ShowS values simply by composing them:
helloworld = hello . world
-- and turn them into Strings by passing them an empty list:
helloworld' = helloworld ""
It's called ShowS because it's used in the implementation of the standard Show typeclass to allow efficient showing of large, deeply-nested structures; as well as show, you can implement showsPrec, which has the type:
showsPrec :: (Show a) => Int -> a -> ShowS
This allows handling of operator precedence, and returns a ShowS value. The standard instances implement this instead of show for efficiency; show a is then defined in terms of it, as showsPrec 0 a "". (This default definition is in the Show typeclass itself, so you can just implement showsPrec for a complete instance.)
showS uses the difference list approach to efficiently concatenate individual components of the shown value. The function takes the value to be shown, and a string to append to the result. The appended string is passed all the way down to the right-most sub-value until it reaches a leaf, where it is actually appended.
There's a description of difference lists (including showS) here http://www.haskell.org/haskellwiki/Difference_list

Resources