well... This code is both demonstration for use case and more sane class + instance typeclass name is selected quite randomly, may be native speaker will select a better one

module Actuative where
import Control.Applicative
import System.IO
import System.IO.Error

-- | minimal complete definition : select
class Applicative f => Actuative f where
-- | select computation conditionally . Side effects of only one two alternative take place
 select      :: f (Either a b)  -- ^ selector
                 -> f (a -> c) -- ^ first alternative
                 -> f (b -> c) -- ^ second alternative
                 -> f c
 -- | correct possible error
 correct     :: f (Either a b) -> f (a -> b) -> f b
 correct i l  = select i l (pure (\x -> x))
 -- | similiar for select, but mimics ArrowChoice
branch :: f (Either a b) -> f (a -> c) -> f (b -> d) -> f (Either c d) branch i l r = select i (pure (\f x -> Left (f x)) <*> l) (pure (\f x -> Right (f x)) <*> r)
 -- | execute only if Left
 onLeft      :: f (Either a b) -> f (a -> c) -> f (Either c b)
 onLeft i l   = branch i l (pure (\x -> x))
 -- | execute only if Right
 onRight     :: f (Either a b) -> f (b -> c) -> f (Either a c)
 onRight i r  = branch i (pure (\x -> x)) r

-- | This is streaming parser combinators for writing LR (k) grammars
newtype Parse a = Parse { runParse :: Handle -> IO a }

-- | this function is one of reasons. If EOF occurs, we should produce result. If not, we should continue parsing. Monadic interface, however, gives too much freedom.
next :: Parse (Maybe Char)
next = Parse $ \h -> catchIOError (fmap Just $ hGetChar h) (const $ return Nothing)

instance Functor Parse where
 fmap f s = pure f <*> s

instance Applicative Parse where
 pure a  = Parse $ \_ -> return a
 (Parse l) <*> (Parse r) = Parse $ \h -> do
           lr <- l h
           rr <- r h
           return $ lr rr

--  instance for Actuative.
instance Actuative Parse where
 select (Parse i) (Parse l) (Parse r) = Parse $ \h -> do
  ir <- i h
  case ir of
   Left  lv -> do
            lr <- l h
            return $ lr lv
   Right rv -> do
            rr <- r h
            return $ rr rv




On 07/26/2012 12:48 PM, Ross Paterson wrote:
On Wed, Jul 25, 2012 at 09:22:23PM +0100, Евгений Пермяков wrote:
So, it seems for me, that Applicative API should be extended with
typeclass for making choice what actions to execute depending on result
of some test (pattern matching). Is there any reasonable definition of
such typeclass or clear explanation, why such typeclass is unneeded?

The possible extension may look somehow like this:

class Applicative a => Branching a where
   branch :: a (Either b c) -> (a b -> a d) -> (a c -> a d) -> a d
Do you have any instances in mind?

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe


_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to