make some Applicative functions into methods, and split off Data.Functor (proposal...
authorRoss Paterson <ross@soi.city.ac.uk>
Tue, 15 Sep 2009 17:31:09 +0000 (17:31 +0000)
committerRoss Paterson <ross@soi.city.ac.uk>
Tue, 15 Sep 2009 17:31:09 +0000 (17:31 +0000)
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.

Control/Applicative.hs
Data/Functor.hs [new file with mode: 0644]
GHC/Base.lhs
base.cabal

index 1d62e0a..e60182d 100644 (file)
@@ -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 (file)
index 0000000..c3e36fd
--- /dev/null
@@ -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
index 71876d3..62612b0 100644 (file)
@@ -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
index 4ea4e3d..9bdfd2c 100644 (file)
@@ -136,6 +136,7 @@ Library {
         Data.Fixed,
         Data.Foldable
         Data.Function,
+        Data.Functor,
         Data.HashTable,
         Data.IORef,
         Data.Int,