# Prelude extensions

### From HaskellWiki

(Difference between revisions)

Atilaromero (Talk | contribs) |
m (Corrected type signature of mapSnd) |
||

(14 intermediate revisions by 7 users not shown) | |||

Line 1: | Line 1: | ||

− | + | __TOC__ | |

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

== Tuples == | == Tuples == | ||

Line 39: | Line 11: | ||

-- | Apply a function to the second element of a pair | -- | Apply a function to the second element of a pair | ||

− | mapSnd :: (b -> c) -> (a, b) -> ( | + | mapSnd :: (b -> c) -> (a, b) -> (a, c) |

mapSnd f (a, b) = (a, f b) | mapSnd f (a, b) = (a, f b) | ||

Line 47: | Line 19: | ||

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

− | + | [http://haskell.org/ghc/docs/latest/html/libraries/fgl/Data-Graph-Inductive-Query-Monad.html#1 Data.Graph.Inductive.Query.Monad module (section ''Additional Graph Utilities'')] contains <hask>mapFst</hask>, <hask>mapSnd</hask>, and also a function <hask>><</hask> corresponding to <hask>mapPair</hask>. Another implementation of these functions in the standard libraries: using <hask>first</hask>, <hask>second</hask>, <hask>***</hask> arrow operations overloaded for functions (as special arrows), see [http://haskell.org/ghc/docs/latest/html/libraries/base/Control-Arrow.html Control.Arrow] module, or [[Arrow]] HaskellWiki page. | |

− | + | See also [[pointfree|point-free]] programming. | |

− | + | === Treating pairs and lists in the same way === | |

− | + | We can define a Pair class which allows us to process both pairs and non-empty lists using the same operator: | |

<haskell> | <haskell> | ||

− | + | import Control.Arrow ((***)) | |

− | + | ||

− | + | infixl 4 <**> | |

− | + | ||

− | + | class Pair p x y | p -> x, p -> y where | |

− | + | toPair :: p -> (x, y) | |

− | + | (<**>) :: (x -> a -> b) -> (y -> a) -> p -> b | |

− | + | (<**>) f g = uncurry id . (f *** g) . toPair | |

− | - | + | |

− | + | instance Pair (a, b) a b where | |

− | - | + | toPair = id |

− | + | ||

− | + | instance Pair [a] a [a] where | |

− | + | toPair l = (head l, tail l) | |

− | + | ||

− | + | ||

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

+ | |||

+ | == Matrices == | ||

+ | |||

+ | A simple representation of matrices is as lists of lists of numbers: | ||

+ | <haskell> | ||

+ | newtype Matrix a = Matrix [[a]] deriving (Eq, Show) | ||

+ | </haskell> | ||

+ | These matrices may be made an instance of <hask>Num</hask> | ||

+ | (though the definitions of <hask>abs</hask> and <hask>signum</hask> are just fillers): | ||

+ | <haskell> | ||

+ | instance Num a => Num (Matrix a) where | ||

+ | Matrix as + Matrix bs = Matrix (zipWith (zipWith (+)) as bs) | ||

+ | Matrix as - Matrix bs = Matrix (zipWith (zipWith (-)) as bs) | ||

+ | Matrix as * Matrix bs = | ||

+ | Matrix [[sum $ zipWith (*) a b | b <- transpose bs] | a <- as] | ||

+ | negate (Matrix as) = Matrix (map (map negate) as) | ||

+ | fromInteger x = Matrix (iterate (0:) (fromInteger x : repeat 0)) | ||

+ | abs m = m | ||

+ | signum _ = 1 | ||

+ | </haskell> | ||

+ | The <hask>fromInteger</hask> method builds an infinite matrix, but addition and subtraction work even with infinite matrices, and multiplication works as long as either the first matrix is of finite width or the second is of finite height. | ||

+ | Applying the linear transformation defined by a matrix to a vector is | ||

+ | <haskell> | ||

+ | apply :: Num a => Matrix a -> [a] -> [a] | ||

+ | apply (Matrix as) b = [sum (zipWith (*) a b) | a <- as] | ||

+ | </haskell> | ||

+ | |||

+ | == Data.Either extensions == | ||

+ | |||

+ | |||

+ | <haskell> | ||

+ | import Data.Either | ||

+ | |||

+ | either', trigger, trigger_, switch :: (a -> b) -> (a -> b) -> Either a a -> Either b b | ||

+ | |||

+ | either' f g (Left x) = Left (f x) | ||

+ | either' f g (Right x) = Right (g x) | ||

+ | |||

+ | trigger f g (Left x) = Left (f x) | ||

+ | trigger f g (Right x) = Left (g x) | ||

+ | |||

+ | trigger_ f g (Left x) = Right (f x) | ||

+ | trigger_ f g (Right x) = Right (g x) | ||

+ | |||

+ | switch f g (Left x) = Right (f x) | ||

+ | switch f g (Right x) = Left (g x) | ||

+ | |||

+ | sure :: (a->b) -> Either a a -> b | ||

+ | sure f = either f f | ||

+ | |||

+ | sure' :: (a->b) -> Either a a -> Either b b | ||

+ | sure' f = either' f f | ||

+ | </haskell> | ||

+ | |||

+ | [[Category:Code]] | ||

+ | |||

+ | == See also == | ||

+ | [[List function suggestions]] |

## Latest revision as of 00:27, 27 September 2007

## Contents |

## [edit] 1 Tuples

It is often necessary to apply functions to either the first or the second part of a pair. This is often considered a form of mapping (like map from Data.List).

-- | Apply a function to the first element of a pair mapFst :: (a -> c) -> (a, b) -> (c, b) mapFst f (a, b) = (f a, b) -- | Apply a function to the second element of a pair mapSnd :: (b -> c) -> (a, b) -> (a, c) mapSnd f (a, b) = (a, f b) -- | Apply a function to both elements of a pair mapPair :: (a -> c, b -> d) -> (a, b) -> (c, d) mapPair (f, g) (a, b) = (f a, g b)

*Additional Graph Utilities*) contains

mapFst

mapSnd

><

mapPair

first

second

***

See also point-free programming.

### [edit] 1.1 Treating pairs and lists in the same way

We can define a Pair class which allows us to process both pairs and non-empty lists using the same operator:

import Control.Arrow ((***)) infixl 4 <**> class Pair p x y | p -> x, p -> y where toPair :: p -> (x, y) (<**>) :: (x -> a -> b) -> (y -> a) -> p -> b (<**>) f g = uncurry id . (f *** g) . toPair instance Pair (a, b) a b where toPair = id instance Pair [a] a [a] where toPair l = (head l, tail l)

## [edit] 2 Matrices

A simple representation of matrices is as lists of lists of numbers:

newtype Matrix a = Matrix [[a]] deriving (Eq, Show)

Num

abs

signum

instance Num a => Num (Matrix a) where Matrix as + Matrix bs = Matrix (zipWith (zipWith (+)) as bs) Matrix as - Matrix bs = Matrix (zipWith (zipWith (-)) as bs) Matrix as * Matrix bs = Matrix [[sum $ zipWith (*) a b | b <- transpose bs] | a <- as] negate (Matrix as) = Matrix (map (map negate) as) fromInteger x = Matrix (iterate (0:) (fromInteger x : repeat 0)) abs m = m signum _ = 1

fromInteger

Applying the linear transformation defined by a matrix to a vector is

apply :: Num a => Matrix a -> [a] -> [a] apply (Matrix as) b = [sum (zipWith (*) a b) | a <- as]

## [edit] 3 Data.Either extensions

import Data.Either either', trigger, trigger_, switch :: (a -> b) -> (a -> b) -> Either a a -> Either b b either' f g (Left x) = Left (f x) either' f g (Right x) = Right (g x) trigger f g (Left x) = Left (f x) trigger f g (Right x) = Left (g x) trigger_ f g (Left x) = Right (f x) trigger_ f g (Right x) = Right (g x) switch f g (Left x) = Right (f x) switch f g (Right x) = Left (g x) sure :: (a->b) -> Either a a -> b sure f = either f f sure' :: (a->b) -> Either a a -> Either b b sure' f = either' f f