diff --git a/simple-pipe.cabal b/simple-pipe.cabal
--- a/simple-pipe.cabal
+++ b/simple-pipe.cabal
@@ -2,7 +2,7 @@
 cabal-version:	>= 1.8
 
 name:		simple-pipe
-version:	0.0.0.13
+version:	0.0.0.14
 stability:	Experimental
 author:		Yoshikuni Jujo <PAF01143@nifty.ne.jp>
 maintainer:	Yoshikuni Jujo <PAF01143@nifty.ne.jp>
@@ -61,13 +61,6 @@
     > 		Just s -> lift (putStrLn s) >> writeString
     > 		_ -> return ()
     >
-    > convert :: Monad m => (a -> b) -> Pipe a b m ()
-    > convert f = do
-    > 	mx <- await
-    > 	case mx of
-    > 		Just x -> yield (f x) >> convert f
-    > 		_ -> return ()
-    >
     > takeP :: Monad m => Int -> Pipe a a m ()
     > takeP 0 = return ()
     > takeP n = do
@@ -87,13 +80,13 @@
 source-repository	this
     type:	git
     location:	git://github.com/YoshikuniJujo/simple-pipe.git
-    tag:	simple-pipe-0.0.0.13
+    tag:	simple-pipe-0.0.0.14
 
 library
     hs-source-dirs:	src
     exposed-modules:
         Data.Pipe,
-        Data.Pipe.Basic, Data.Pipe.List, Data.Pipe.IO, Data.Pipe.ByteString
+        Data.Pipe.List, Data.Pipe.IO, Data.Pipe.ByteString
     build-depends:
         base == 4.*, monad-control == 0.3.*, lifted-base == 0.2.*,
         monads-tf == 0.1.*, bytestring == 0.10.*
diff --git a/src/Data/Pipe.hs b/src/Data/Pipe.hs
--- a/src/Data/Pipe.hs
+++ b/src/Data/Pipe.hs
@@ -1,7 +1,9 @@
 {-# LANGUAGE TupleSections, TypeFamilies, FlexibleContexts, RankNTypes,
 	PackageImports #-}
 
-module Data.Pipe ( PipeClass(..), Pipe, finally, bracket ) where
+module Data.Pipe (
+	PipeClass(..), PipeChoice(..), convert,
+	Pipe, finally, bracket ) where
 
 import Control.Applicative
 import Control.Monad
@@ -25,11 +27,48 @@
 
 	p `finalize` f = p `onBreak` f `onDone` f
 
+convert :: (PipeClass p, Monad m, Monad (p a b m)) => (a -> b) -> p a b m ()
+convert f = await >>= maybe (return ()) ((>> convert f) . yield . f)
+
+-- | Minimal complete definition: 'appLeft'
+
+class PipeClass pc => PipeChoice pc where
+	appLeft :: Monad m => pc b c m () -> pc (Either b d) (Either c d) m ()
+	appRight :: (Monad m, Monad (pc (Either d b) (Either b d) m),
+		Monad (pc (Either c d) (Either d c) m)) =>
+		pc b c m () -> pc (Either d b) (Either d c) m ()
+	(++++) :: (Monad m, Monad (pc (Either c' c) (Either c c') m),
+		Monad (pc (Either c b') (Either b' c) m) ) =>
+		pc b c m () -> pc b' c' m () -> pc (Either b b') (Either c c') m ()
+	(||||) :: (Monad m, Monad (pc (Either d d) d m),
+		Monad (pc (Either d c) (Either c d) m),
+		Monad (pc (Either d d) (Either d d) m)) =>
+		pc b d m () -> pc c d m () -> pc (Either b c) d m ()
+
+	appRight f = convert mirror =$= appLeft f =$= convert mirror
+		where
+		mirror (Left x) = Right x
+		mirror (Right y) = Left y
+	f ++++ g = appLeft f =$= appRight g
+	f |||| g = (f ++++ g) =$= convert untag
+		where
+		untag (Left x) = x
+		untag (Right y) = y
+
 data Pipe i o m r
 	= Ready (m ()) o (Pipe i o m r)
 	| Need (m ()) (Maybe i -> Pipe i o m r)
 	| Done (m ()) r
 	| Make (m ()) (m (Pipe i o m r))
+
+instance PipeChoice Pipe where
+	appLeft (Ready f o p) = Ready f (Left o) $ appLeft p
+	appLeft (Need f p) = Need f $ \mei -> case mei of
+		Just (Left i) -> appLeft . p $ Just i
+		Just (Right i) -> yield (Right i) >> appLeft (p Nothing)
+		_ -> appLeft $ p Nothing
+	appLeft (Done f r) = Done f r
+	appLeft (Make f p) = Make f $ appLeft `liftM` p
 
 instance MonadWriter m => MonadWriter (Pipe i o m) where
 	type WriterType (Pipe i o m) = WriterType m
diff --git a/src/Data/Pipe/Basic.hs b/src/Data/Pipe/Basic.hs
deleted file mode 100644
--- a/src/Data/Pipe/Basic.hs
+++ /dev/null
@@ -1,6 +0,0 @@
-module Data.Pipe.Basic (convert) where
-
-import Data.Pipe
-
-convert :: (PipeClass p, Monad m, Monad (p a b m)) => (a -> b) -> p a b m ()
-convert f = await >>= maybe (return ()) ((>> convert f) . yield . f)
