From: Ross Paterson Date: Tue, 15 Sep 2009 17:31:09 +0000 (+0000) Subject: make some Applicative functions into methods, and split off Data.Functor (proposal... X-Git-Tag: ghc-darcs-git-switchover~315 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=ccf049137fe5848ce934315e4de18cecf75b08e3;p=ghc-base.git make some Applicative functions into methods, and split off Data.Functor (proposal #3335) The following functions (<$) :: Functor f => a -> f b -> f a (*>) :: Applicative f => f a -> f b -> f b (<*) :: Applicative f => f a -> f b -> f a some :: Alternative f => f a -> f [a] many :: Alternative f => f a -> f [a] are moved into the corresponding classes, with the existing implementations as default definitions. This gives people creating instances the option of defining specialized implementations of these functions, though they should be equivalent to the default definitions. Although (<$) is now a method of the Functor class, it is hidden in the re-export by the Prelude, Control.Monad and Monad. The new module Data.Functor exposes the full class, plus the function (<$>). These are also re-exported by Control.Applicative. --- diff --git a/Control/Applicative.hs b/Control/Applicative.hs index 1d62e0a..e60182d 100644 --- a/Control/Applicative.hs +++ b/Control/Applicative.hs @@ -30,9 +30,9 @@ module Control.Applicative ( -- * Instances Const(..), WrappedMonad(..), WrappedArrow(..), ZipList(..), -- * Utility functions - (<$>), (<$), (*>), (<*), (<**>), + (<$>), (<$), (<**>), liftA, liftA2, liftA3, - optional, some, many + optional, ) where import Prelude hiding (id,(.)) @@ -42,10 +42,10 @@ import Control.Arrow (Arrow(arr, (&&&)), ArrowZero(zeroArrow), ArrowPlus((<+>))) import Control.Monad (liftM, ap, MonadPlus(..)) import Control.Monad.Instances () +import Data.Functor ((<$>), (<$)) import Data.Monoid (Monoid(..)) infixl 3 <|> -infixl 4 <$>, <$ infixl 4 <*>, <*, *>, <**> -- | A functor with application. @@ -64,6 +64,12 @@ infixl 4 <*>, <*, *>, <**> -- [/interchange/] -- @u '<*>' 'pure' y = 'pure' ('$' y) '<*>' u@ -- +-- [/ignore left value/] +-- @u '*>' v = 'pure' ('const' 'id') '<*>' u '<*>' v@ +-- +-- [/ignore right value/] +-- @u '<*' v = 'pure' 'const' '<*>' u '<*>' v@ +-- -- The 'Functor' instance should satisfy -- -- @ @@ -71,6 +77,8 @@ infixl 4 <*>, <*, *>, <**> -- @ -- -- If @f@ is also a 'Monad', define @'pure' = 'return'@ and @('<*>') = 'ap'@. +-- +-- Minimal complete definition: 'pure' and '<*>'. class Functor f => Applicative f where -- | Lift a value. @@ -79,13 +87,41 @@ class Functor f => Applicative f where -- | Sequential application. (<*>) :: f (a -> b) -> f a -> f b + -- | Sequence actions, discarding the value of the first argument. + (*>) :: f a -> f b -> f b + (*>) = liftA2 (const id) + + -- | Sequence actions, discarding the value of the second argument. + (<*) :: f a -> f b -> f a + (<*) = liftA2 const + -- | A monoid on applicative functors. +-- +-- Minimal complete definition: 'empty' and '<|>'. +-- +-- 'some' and 'many' should be the least solutions of the equations: +-- +-- * @some v = (:) '<$>' v '<*>' many v@ +-- +-- * @many v = some v '<|>' 'pure' []@ class Applicative f => Alternative f where -- | The identity of '<|>' empty :: f a -- | An associative binary operation (<|>) :: f a -> f a -> f a + -- | One or more. + some :: f a -> f [a] + some v = some_v + where many_v = some_v <|> pure [] + some_v = (:) <$> v <*> many_v + + -- | Zero or more. + many :: f a -> f [a] + many v = many_v + where many_v = some_v <|> pure [] + some_v = (:) <$> v <*> many_v + -- instances for Prelude types instance Applicative Maybe where @@ -169,22 +205,6 @@ instance Applicative ZipList where -- extra functions --- | A synonym for 'fmap'. -(<$>) :: Functor f => (a -> b) -> f a -> f b -f <$> a = fmap f a - --- | Replace the value. -(<$) :: Functor f => a -> f b -> f a -(<$) = (<$>) . const - --- | Sequence actions, discarding the value of the first argument. -(*>) :: Applicative f => f a -> f b -> f b -(*>) = liftA2 (const id) - --- | Sequence actions, discarding the value of the second argument. -(<*) :: Applicative f => f a -> f b -> f a -(<*) = liftA2 const - -- | A variant of '<*>' with the arguments reversed. (<**>) :: Applicative f => f a -> f (a -> b) -> f b (<**>) = liftA2 (flip ($)) @@ -205,15 +225,3 @@ liftA3 f a b c = f <$> a <*> b <*> c -- | One or none. optional :: Alternative f => f a -> f (Maybe a) optional v = Just <$> v <|> pure Nothing - --- | One or more. -some :: Alternative f => f a -> f [a] -some v = some_v - where many_v = some_v <|> pure [] - some_v = (:) <$> v <*> many_v - --- | Zero or more. -many :: Alternative f => f a -> f [a] -many v = many_v - where many_v = some_v <|> pure [] - some_v = (:) <$> v <*> many_v diff --git a/Data/Functor.hs b/Data/Functor.hs new file mode 100644 index 0000000..c3e36fd --- /dev/null +++ b/Data/Functor.hs @@ -0,0 +1,28 @@ +----------------------------------------------------------------------------- +-- | +-- Module : Data.Functor +-- Copyright : (c) The University of Glasgow 2001 +-- License : BSD-style (see the file libraries/base/LICENSE) +-- +-- Maintainer : libraries@haskell.org +-- Stability : provisional +-- Portability : portable +-- +-- Functors: uniform action over a parameterized type, generalizing the +-- 'map' function on lists. + +module Data.Functor + ( + Functor(fmap, (<$)), + (<$>), + ) where + +#ifdef __GLASGOW_HASKELL__ +import GHC.Base (Functor(..)) +#endif + +infixl 4 <$> + +-- | An infix synonym for 'fmap'. +(<$>) :: Functor f => (a -> b) -> f a -> f b +(<$>) = fmap diff --git a/GHC/Base.lhs b/GHC/Base.lhs index 71876d3..62612b0 100644 --- a/GHC/Base.lhs +++ b/GHC/Base.lhs @@ -113,6 +113,7 @@ import GHC.Unit () infixr 9 . infixr 5 ++ +infixl 4 <$ infixl 1 >>, >>= infixr 0 $ @@ -176,6 +177,12 @@ defined in the "Prelude" satisfy these laws. class Functor f where fmap :: (a -> b) -> f a -> f b + -- | Replace all locations in the input with the same value. + -- The default definition is @'fmap' . 'const'@, but this may be + -- overridden with a more efficient version. + (<$) :: a -> f b -> f a + (<$) = fmap . const + {- | The 'Monad' class defines the basic operations over a /monad/, a concept from a branch of mathematics known as /category theory/. From the perspective of a Haskell programmer, however, it is best to diff --git a/base.cabal b/base.cabal index 4ea4e3d..9bdfd2c 100644 --- a/base.cabal +++ b/base.cabal @@ -136,6 +136,7 @@ Library { Data.Fixed, Data.Foldable Data.Function, + Data.Functor, Data.HashTable, Data.IORef, Data.Int,