Search code examples
haskelltypesnewtype

How to define a Haskell function with an argument of "newtype"?


I've defined a newtype called Poly. Poly is a list representation of a polynomial (a list of Num's), and I'm trying to define a function "chop" that takes off excess 0's from the end of a Poly.

Chop takes one Poly as an argument, and then returns a Poly. For some reason I'm getting the following error message:

Expected a constraint, but ‘Poly a’ has kind ‘*’ In the type signature for ‘chop’: chop :: Poly a => a -> a

newtype Poly a = P [a]

chop :: Poly a => a -> a
chop l = if (last l) == 0 then chop (init l) else l

Solution

  • In Haskell, the => character in a type signature denotes a type restriction. This is used in conjunction with Haskell typeclasses in order to abstract away implementation details about functions that can be used at a high level of abstraction.

    In your example, Poly a is a completely new type according to the type system, not a typeclass, so your function chop likely is intended to operate on it directly:

    chop :: Poly a -> Poly a
    chop (P l) = if (last l) == 0 then chop (P $ init l) else P l
    

    But wait, this doesn't compile! The restriction comes from the comparison to 0: (last l) == 0. Here we're implicitly saying that we want the elements of our Poly a to be comparable to zero, or in other words a must be an instance of Num a. After all, you wouldn't be able to chop a polynomial of type Poly (Maybe String). Our revised type signature is:

    chop :: Num a => Poly a -> Poly a
    chop (P l) = if (last l) == 0 then chop (P $ init l) else P l
    

    One thing to take into consideration: because you are using a newtype and not a plain old type, Haskell is treating your Poly a as a completely new type. In order to make it interchangeable with lists, you can use a type synonym:

    type Poly a = [a]
    

    This will simplify the implementation of chop:

    chop :: Num a => Poly a -> Poly a
    chop l = if (last l) == 0 then chop (init l) else l