Mark Needham

Thoughts on Software Development

Haskell: Mixed type lists

with 3 comments

I’ve been continuing to work through the exercises in The Little Schemer and came across a problem which needed me to write a function to take a mixed list of Integers and Strings and filter out the Integers.

As I mentioned in my previous post I’ve been doing the exercises in Haskell but I thought I might struggle with that approach here because Haskell collections are homogeneous i.e. all the elements need to be of the same type.

I read about existentially quantified types but they seemed a bit complicated and instead I decided to use the Dynamic interface.

Using Dynamic we can define a function to strip out the numbers like this:

import Data.Dynamic
import Data.Maybe
 
noNums :: [Dynamic] -> [Dynamic]
noNums lat = cond [(null lat, []), 
                   (isNumber (head lat), noNums (tail lat)),
                   (otherwise, head lat : noNums (tail lat))]
 
justInt :: Dynamic -> Maybe Int
justInt dyn = fromDynamic dyn :: Maybe Int
 
isNumber :: Dynamic -> Bool
isNumber x = isJust $ justInt x

We can then call the function like this:

> map toString $ noNums [toDyn (5 :: Int), toDyn "pears", toDyn (6 :: Int), toDyn "prunes", toDyn (9 :: Int), toDyn "dates"]
[Just "pears",Just "prunes",Just "dates"]
toString :: Dynamic -> Maybe String
toString dyn = fromDynamic dyn

fromDynamic eventually makes a call to unSafeCoerce#:

The function unsafeCoerce# allows you to side-step the typechecker entirely. That is, it allows you to coerce any type into any other type. If you use this function, you had better get it right, otherwise segmentation faults await. It is generally used when you want to write a program that you know is well-typed, but where Haskell’s type system is not expressive enough to prove that it is well typed.

I wanted to try and make the ‘isNumber’ function handle any numeric type rather than just Ints but I haven’t quite worked out how to do that.

Obviously I’m only using Dynamic here because the exercise requires it but I’m not sure what real life situation would require its use.

If anyone has used it before or knows a use case I’d be interested to know what it is!

Be Sociable, Share!

Written by Mark Needham

June 19th, 2012 at 11:09 pm

Posted in Haskell

Tagged with

  • zorg

    You probably should stick with dynamically typed FPish language for this book… fighting Haskell’s type-system is going to get distracting when you get to continuation-passing-style. 
    Apart from the last chapter, code snippets are short so any scheme REPL will do (you don’t even need to install one : http://www.biwascheme.org/). 
    If you like Haskell syntax check out Pure (http://code.google.com/p/pure-lang/).

  • http://www.markhneedham.com/blog Mark Needham

    @83f49a8da1dc030d9f671f521839aecc:disqus yeh I think you’re probably right. I was just curious what the code would look like in Haskell more than anything! 

    pure looks pretty interesting – I haven’t come across it before – thanks for linking.

  • Laurent

    I think the good pattern for this problem is Either, but you can create yours, like that :

    data IntString = I Int | S String

    nonums xs = [x | S x nonums [I 5, S “pears”, I 6, S “prunes”, I 9, S “dates”]
    [“pears”,”prunes”,”dates”]

    Et voilà ! If you want Double or Integer add constructors to IntString.