6

I am new to Haskell, so my question is probably stupid.

I want a function

show2 :: (Show a) => a -> String 

which would return show a for any a, but a if a is itself String. How can I implement it?

P.S. it is great if this function is already implemented somewhere, but I still want to see an example of the implementation.

5
  • 4
    This is generally a bad idea, for what it's worth. Commented Mar 26, 2015 at 22:26
  • By the way, you may already know this but since you are new: The part that comes before the => is called the context (in your case it's Show a). Since there is just one there, you don't have to use parentheses. Commented Mar 27, 2015 at 1:51
  • @LouisWasserman can you explain, why? Commented Mar 27, 2015 at 2:07
  • @Hindsight it's generally inadvisable to want to do any kind of reflectiony logic in Haskell; "exceptions for specific types" and the like are frowned upon. Commented Mar 27, 2015 at 2:11
  • 2
    @Hindsight The reason why it's frowned upon is that parametricity has been found to be extremely valuable property for code to have; this is the idea that if your function is polymorphic in some type variable then it uniformly handles all types the same way. This tends to make code much more reusable, composable, and easy to reason about. Commented Mar 27, 2015 at 4:48

3 Answers 3

6

You can use cast from Data.Typeable

show2 :: (Typeable a, Show a) => a -> String show2 s = maybe (show s) id ms where ms = cast s :: Maybe String 
Sign up to request clarification or add additional context in comments.

Comments

5

You can do this with this piece of dirty and dangerous code:

class Showable a where show2 :: a -> String instance Showable String where show2 = id instance (Show a) => Showable a where show2 = show 

You need -XOverlappingInstances -XFlexibleInstances -XUndecidableInstances to compile and use it.

*Main> show2 "abc" "abc" *Main> show2 3 "3" 

1 Comment

{-# LANGUAGE ... #-} pragmas are usually better than -X flags.
5

The way that Haskell is designed is very much opposed to the concept of an instanceof check. Haskell's design does not incorporate this sort of runtime type check, because Haskell is very focused on strong compilation-time guarantees: a function should not be able to learn the type of its arguments at runtime any more precisely than it knows them at compilation time.

This doesn't meant that the feature doesn't exist in Haskell—Lee's answer demonstrates how to do it—but in Haskell this is an opt-in feature provided by a library, not a core part of the language (unlike a language like Java, where it's a core feature that's always present—you can't opt out of it!).

Note that even in object-oriented programming the instanceof operator is controversial. Many object-oriented programmers very strongly advise against its use. A few examples (out of hundreds):

The advise in all of these tends to be the same: instead of using testing the type of a reference and switching to different behaviors based on it, use polymorphism: define an interface or class that has a method for the operation you want, and have the objects that you were testing with instanceof implement their own versions of that method to do the right thing.

This advice can be translated straightforwardly to Haskell:

  1. Define your own type class to represent the behavior you want
  2. Implement this type class for each of the types that you're interested in, with the correct behavior for each.

So, you could do something like this:

class ToString a where toString :: a -> String instance ToString String where toString str = str instance ToString Integer where toString i = show i -- ... 

1 Comment

Great! And can I do something like instance Show a => ToString a ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.