Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Functions of `a` on `newtype a`

Let's say I have the following newtype:

newtype Foo = Foo Integer deriving (Eq, Show)

Is there a concise way to add two Foo's:

(Foo 10) + (Foo 5) == Foo 15

or get the max:

max (Foo 10) (Foo 5) == Foo 5?

I'm curious if it's possible to easily use functions of a for a newtype a rather than do:

addFoo :: Foo -> Foo -> Foo
addFoo (Foo x) (Foo y) = Foo $ x + y
like image 699
Kevin Meredith Avatar asked Oct 06 '14 02:10

Kevin Meredith


2 Answers

Just as haskell98 knows how to derive those Eq and Show instances for you, you can turn on the GeneralizedNewtypeDeriving extension to ghc to get the Num and Ord instances you need:

Prelude> :set -XGeneralizedNewtypeDeriving 
Prelude> newtype Foo = Foo Integer deriving (Eq, Show, Num, Ord)
Prelude> (Foo 10) + (Foo 5) == Foo 15
True
Prelude> max (Foo 10) (Foo 5) == Foo 5
False
like image 66
jberryman Avatar answered Sep 25 '22 09:09

jberryman


You want to lift functions of the type Integer -> Integer -> Integer to Foo -> Foo -> Foo. To do so you could define utility functions:

liftFoo :: (Integer -> Integer) -> Foo -> Foo
liftFoo f (Foo a) = Foo $ f a

liftFoo2 :: (Integer -> Integer -> Integer) -> Foo -> Foo -> Foo
liftFoo2 f (Foo a) (Foo b) = Foo $ f a b

-- and so on

Then you could use it as follows:

liftFoo2 (+) (Foo 10) (Foo 5)

liftFoo2 max (Foo 10) (Foo 5)

This has the advantage of not requiring an extension.


Another option is to make the definition of the Foo newtype more permissible so that you could make it an instance of Functor and Applicative:

import Control.Applicative

newtype Foo a = Foo a deriving (Eq, Show)

foo :: Integer -> Foo Integer
foo = Foo

instance Functor Foo where
    fmap f (Foo a) = Foo $ f a

instance Applicative Foo where
    pure = Foo
    (Foo f) <*> (Foo a) = Foo $ f a

Now you could do the following:

(+) <$> foo 10 <*> foo 5

max <$> foo 10 <*> foo 5

Because foo is specialized to the Integer type you don't lose any benefits of type checking.

like image 35
Aadit M Shah Avatar answered Sep 22 '22 09:09

Aadit M Shah