# Lazy functors

### From HaskellWiki

(Difference between revisions)

(compare lazy and strict pattern matching for Functor instances and friends) |
(definition of Identity) |
||

Line 56: | Line 56: | ||

sequenceA (fmap Identity x) = Identity x | sequenceA (fmap Identity x) = Identity x | ||

</haskell> | </haskell> | ||

+ | |||

+ | <!-- | ||

+ | newtype Identity a = Identity a | ||

+ | deriving (Show) | ||

+ | |||

+ | instance Functor Identity where | ||

+ | fmap f (Identity a) = Identity (f a) | ||

+ | |||

+ | instance Applicative Identity where | ||

+ | pure f = Identity f | ||

+ | (Identity f) <*> (Identity a) = Identity (f a) | ||

+ | --> | ||

With the first definitions with lazy matching the laws are violated: | With the first definitions with lazy matching the laws are violated: |

## Revision as of 10:30, 5 June 2011

## 1 Question

I have a data type like

data Pair a = Pair a a

Functor

with lazy pattern matching or with strict pattern matching?

That is, shall I define

instance Functor Pair where fmap f ~(Pair a b) = Pair (f a) (f b) instance Applicative Pair where pure a = Pair a a ~(Pair fa fb) <*> ~(Pair a b) = Pair (fa a) (fb b) instance Fold.Foldable Pair where foldMap = Trav.foldMapDefault instance Trav.Traversable Pair where sequenceA ~(Pair a b) = liftA2 Pair a b

or shall I define

instance Functor Pair where fmap f (Pair a b) = Pair (f a) (f b) instance Applicative Pair where pure a = Pair a a (Pair fa fb) <*> (Pair a b) = Pair (fa a) (fb b) instance Fold.Foldable Pair where foldMap = Trav.foldMapDefault instance Trav.Traversable Pair where sequenceA (Pair a b) = liftA2 Pair a b

?

## 2 Answer

We can deduce the answers from the following laws applied to undefined values.

import Control.Monad.Identity (Identity(Identity)) fmap id x == x pure id <*> x == x f <*> pure x == pure ($x) <*> f -- there are no laws mentioned in the Traversable documentation, -- but I find the following one natural enough sequenceA (fmap Identity x) = Identity x

With the first definitions with lazy matching the laws are violated:

fmap id undefined == Pair undefined undefined -- because of laziness in the second operand of <*> we get: pure id <*> undefined == Pair undefined undefined -- if the second operand is matched strictly, and the first one lazily, -- then we get: undefined <*> pure undefined == Pair undefined undefined pure ($ undefined) <*> undefined == undefined -- given that fmap matches strict now, since lazy matching is incorrect sequenceA (fmap Identity undefined) == Identity (Pair undefined undefined)

In contrast to that the strict pattern matching is correct in this respect:

fmap id undefined == undefined pure id <*> undefined == undefined undefined <*> pure undefined == undefined pure ($ undefined) <*> undefined == undefined sequenceA (fmap Identity undefined) = Identity undefined

It is a good idea to comply with these laws since they minimize the surprise of the users of your data type, including yourself.

!

(Pair undefined undefined)

undefined

That is, in this case the laws would hold independent of the mode of pattern matching. However, this shall not suggest, that using strict record fields is generally prefered