Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List of showables OOP-style in Haskell?

Tags:

haskell

I want to build a list of different things which have one property in common, namely, they could be turned into string. The object-oriented approach is straightforward: define interface Showable and make classes of interest implement it. Second point can in principle be a problem when you can't alter the classes, but let's pretend this is not the case. Then you create a list of Showables and fill it with objects of these classes without any additional noise (e.g. upcasting is usually done implicitly). Proof of concept in Java is given here.

My question is what options for this do I have in Haskell? Below I discuss approaches that I've tried and which don't really satisfy me.

Approach 1: existensials. Works but ugly.

{-# LANGUAGE ExistentialQuantification #-} data Showable = forall a. Show a => Sh a  aList :: [Showable] aList = [Sh (1 :: Int), Sh "abc"] 

The main drawback for me here is the necessity for Sh when filling the list. This closely resembles upcast operations which are implicitly done in OO-languages.

More generally, the dummy wrapper Showable for the thing which is already in the language — Show type class — adds extra noise in my code. No good.

Approach 2: impredicatives. Desired but does not work.

The most straightforward type for such a list for me and what I really desire would be:

{-# LANGUAGE ImpredicativeTypes #-} aList :: [forall a. Show a => a] aList = [(1 :: Int), "abc"] 

Besides that (as I heard)ImpredicativeTypes is “fragile at best and broken at worst” it does not compile:

Couldn't match expected type ‘a’ with actual type ‘Int’   ‘a’ is a rigid type variable bound by       a type expected by the context: Show a => a 

and the same error for "abc". (Note type signature for 1: without it I receive even more weird message: Could not deduce (Num a) arising from the literal ‘1’).

Approach 3: Rank-N types together with some sort of functional lists (difference lists?).

Instead of problematic ImpredicativeTypes one would probably prefer more stable and wide-accepted RankNTypes. This basically means: move desired forall a. Show a => a out of type constructor (i.e. []) to plain function types. Consequently we need some representation of lists as plain functions. As I barely heard there are such representations. The one I heard of is difference lists. But in Dlist package the main type is good old data so we return to impredicatives. I didn't investigate this line any further as I suspect that it could yield more verbose code than in approach 1. But if you think it won't, please give me an example.

Bottom line: how would you attack such a task in Haskell? Could you give more succinct solution than in OO-language (especially in place of filling a list — see comment for code in approach 1)? Can you comment on how relevant are the approaches listed above?

UPD (based on first comments): the question is of course simplified for the purpose of readability. The real problem is more about how to store things which share the same type class, i.e. can be processed later on in a number of ways (Show has only one method, but other classes can have more than one). This factors out solutions which suggest apply show method right when filling a list.

like image 609
Artem Pelenitsyn Avatar asked Nov 07 '15 19:11

Artem Pelenitsyn


People also ask

How do you find the type of an object in Haskell?

If you are using an interactive Haskell prompt (like GHCi) you can type :t <expression> and that will give you the type of an expression. e.g. or e.g.

Is Haskell OOP?

Haskell isn't an object-oriented language. All of the functionality built here from scratch already exists in a much more powerful form, using Haskell's type system.

Are there classes in Haskell?

Haskell classes are roughly similar to a Java interface. Like an interface declaration, a Haskell class declaration defines a protocol for using an object rather than defining an object itself.

Does Haskell have inheritance?

Does Haskell have inheritance? Well, no, it doesn't, because Haskell does not have objects, and inheritance is a relationship between two objects. Objects are a combination of internal state (data) and methods (behavior).


1 Answers

Since evaluation is lazy in Haskell, how about just creating a list of the actual strings?

showables = [ show 1, show "blah", show 3.14 ] 
like image 107
ErikR Avatar answered Sep 21 '22 13:09

ErikR