Haskell Existential Types - haskell

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

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

Return `show a` if (Show a) exists, otherwise its type representation if (Typeable a)

I would like to write
class Described a where
describe :: a -> String
instance {-# OVERLAPPING #-} (Show a) => Described a where
describe = show
instance {-# OVERLAPPABLE #-} (Typeable a) => Described a where
describe = show . typeOf
This won't work because the right hand side of each instance is the same. I thought would be solved by having a look at https://wiki.haskell.org/GHC/AdvancedOverlap but it seems that I need to define instances for many existing types to make any of these solutions work. What would be the best solution here?
The standard trick for guiding instance selection is to make a new type. So:
newtype DescribeViaTypeable a = DVT a
newtype DescribeViaShow a = DVS a
instance Show a => Described (DescribeViaShow a) where describe (DVS x) = show x
instance Typeable a => Described (DescribeViaTypeable a) where describe (DVT x) = show (typeOf x)
Now callers may choose which kind of description they like if both are available, and data types can be explicit about which kind of description they expect to be available for their fields, eliminating any magic.

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

Make a typeclass instance automatically an instance of another

What I'd like to achieve is that any instance of the following class (SampleSpace) should automatically be an instance of Show, because SampleSpace contains the whole interface necessary to create a String representation and hence all possible instances of the class would be virtually identical.
{-# LANGUAGE FlexibleInstances #-}
import Data.Ratio (Rational)
class SampleSpace space where
events :: Ord a => space a -> [a]
member :: Ord a => a -> space a -> Bool
probability :: Ord a => a -> space a -> Rational
instance (Ord a, Show a, SampleSpace s) => Show (s a) where
show s = showLines $ events s
where
showLines [] = ""
showLines (e:es) = show e ++ ": " ++ (show $ probability e s)
++ "\n" ++ showLines es
Since, as I found out already, while matching instance declarations GHC only looks at the head, and not at contraints, and so it believes Show (s a) is about Rational as well:
[1 of 1] Compiling Helpers.Probability ( Helpers/Probability.hs, interpreted )
Helpers/Probability.hs:21:49:
Overlapping instances for Show Rational
arising from a use of ‘show’
Matching instances:
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance (Ord a, Show a, SampleSpace s) => Show (s a)
-- Defined at Helpers/Probability.hs:17:10
In the expression: show
In the first argument of ‘(++)’, namely ‘(show $ probability e s)’
In the second argument of ‘(++)’, namely
‘(show $ probability e s) ++ "" ++ showLines es
Question: is it possible (otherwise than by enabling overlapping instances) to make any instance of a typeclass automatically an instance of another too?
tl;dr: don't do that, or, if you insist, use -XOverlappingInstances.
This is not what the Show class is there for. Show is for simply showing plain data, in a way that is actually Haskell code and can be used as such again, yielding the original value.
SampleSpace should perhaps not be a class in the first place. It seems to be basically the class of types that have something like Map a Rational associated with them. Why not just use that as a field in a plain data type?
Even if we accept the design... such a generic Show instance (or, indeed, generic instance for any single-parameter class) runs into problems when someone makes another instance for a concrete type – in the case of Show, there are of course already plenty of instances around. Then how should the compiler decide which of the two instances to use? GHC can do it, in fact: if you turn on the -XOverlappingInstances extension, it will select the more specific one (i.e. instance SampleSpace s => Show (s a) is “overridden” by any more specific instance), but really this isn't as trivial as may seem – what if somebody defined another such generic instance? Crucial to recall: Haskell type classes are always open, i.e. basically the compiler has to assume that all types could possibly in any class. Only when a specific instance is invoke will it actually need the proof for that, but it can never proove that a type isn't in some class.
What I'd recommend instead – since that Show instance doesn't merely show data, it should be made a different function. Either
showDistribution :: (SampleSpace s, Show a, Ord a) => s a -> String
or indeed
showDistribution :: (Show a, Ord a) => SampleSpace a -> String
where SampleSpace is a single concrete type, instead of a class.

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"

Resources