[Haskell-cafe] Polymorphic type

Jared Updike jupdike at gmail.com
Thu Jun 22 14:32:43 EDT 2006


On 6/22/06, Sara Kenedy <sarakenedy at gmail.com> wrote:
> Hello all,
>
> Now I am trying with the function of polymorphic type: This function
> returns the Nth element of list with type a. I try it as below.
>
> getNthElem :: Int -> [a] -> Maybe a
> getNthElemt _ []        = Nothing
> getNthElem 0 _  = Nothing
> getNthElem n s
>                 | n > length s  = Nothing
>                 | otherwise     = Just ((drop (n-1) (take n s))!!0)
>
> >getNthElem 2 ["a","b","c"]
> Just "b"
>
> However, I do not satisfy with this function because I want to return
> the Nth element of type a, not (Maybe a). For example, I want this
> function:
> getNthElem :: Int -> [a] ->  a
>
> But, I do not know how to define the empty element of type a.

Not all types (especially numbers) have an empty element (what does
that even mean?). Suppose you have a list
  [0, 1, -2, -1, 2]
and you try getNthElemt 4 and your program assumes that the empty
element for integers is 0. How can you tell that 0 from the 0 at the
beginning of the list [0, 1, 2]? Think really hard about what you are
asking and you will see why Maybe a takes the type a and extends it,
in a way, with an empty element, Nothing. To convert it from Maybe a
to a, try, e.g.
  fromJust (Just 4)  ====>  4
(it will give exceptions when Nothing shows up).

> getNthElemt _ []        = ????
> getNthElem 0 _  =  ????

One possiblity is to make a class called empty with a single member:

> class Empty a where
>   empty :: a
> instance Empty [a] where   -- this also makes   "" = empty   for String
>   empty = []
> instance Empty Maybe a where   -- is this desirable?
>   empty = Nothing
> instance Integer where     -- or this?
>   empty = 0
> ...

and then add the constraint to your function:

> getNthElem :: Empty a => Int -> [a] -> a
> getNthElem :: Int -> [a] -> Maybe a
> getNthElemt _ []        = empty
> getNthElem 0 _  = empty
> getNthElem n s
>                 | n > length s  = empty
>                 | otherwise     = ((drop (n-1) (take n s))!!0)
>

but you need overlapping instances to instantiate [a].  Or you could
use MonadPlus and mzero instead of Empty and empty, but that would
only work for List, Maybe and other monads and not for Integer, etc.

Note that in a dynamic language the same thing happens. In python
   4 + None
raises an exception. I don't think it's possible to get away from this
whole "failure" concept (except silently ignore it---in perl   4+null
 yields 4 but is that always the right behavior in all situations? It
makes bugs really hard to find.)

  Jared.
-- 
http://www.updike.org/~jared/
reverse ")-:"


More information about the Haskell-Cafe mailing list