Movatterモバイル変換


[0]ホーム

URL:


{-# LANGUAGE CPP #-}{-# LANGUAGE Trustworthy #-}{-# LANGUAGE NoImplicitPrelude #-}{-# LANGUAGE StandaloneDeriving #-}{-# LANGUAGE PolyKinds, DataKinds, TypeFamilies, TypeOperators, UndecidableInstances #-}------------------------------------------------------------------------------- |-- Module      :  Data.Either-- Copyright   :  (c) The University of Glasgow 2001-- License     :  BSD-style (see the file libraries/base/LICENSE)---- Maintainer  :  libraries@haskell.org-- Stability   :  experimental-- Portability :  portable---- The Either type, and associated operations.-------------------------------------------------------------------------------moduleData.Either(Either(..),either,lefts,rights,isLeft,isRight,fromLeft,fromRight,partitionEithers,)whereimportGHC.BaseimportGHC.ShowimportGHC.Read-- $setup-- Allow the use of some Prelude functions in doctests.-- >>> import Prelude ( (+), (*), length, putStrLn ){--- just for testingimport Test.QuickCheck-}{-|The 'Either' type represents values with two possibilities: a value oftype @'Either' a b@ is either @'Left' a@ or @'Right' b@.The 'Either' type is sometimes used to represent a value which iseither correct or an error; by convention, the 'Left' constructor isused to hold an error value and the 'Right' constructor is used tohold a correct value (mnemonic: \"right\" also means \"correct\").==== __Examples__The type @'Either' 'String' 'Int'@ is the type of values which can be eithera 'String' or an 'Int'. The 'Left' constructor can be used only on'String's, and the 'Right' constructor can be used only on 'Int's:>>> let s = Left "foo" :: Either String Int>>> sLeft "foo">>> let n = Right 3 :: Either String Int>>> nRight 3>>> :type ss :: Either String Int>>> :type nn :: Either String IntThe 'fmap' from our 'Functor' instance will ignore 'Left' values, butwill apply the supplied function to values contained in a 'Right':>>> let s = Left "foo" :: Either String Int>>> let n = Right 3 :: Either String Int>>> fmap (*2) sLeft "foo">>> fmap (*2) nRight 6The 'Monad' instance for 'Either' allows us to chain together multipleactions which may fail, and fail overall if any of the individualsteps failed. First we'll write a function that can either parse an'Int' from a 'Char', or fail.>>> import Data.Char ( digitToInt, isDigit )>>> :{    let parseEither :: Char -> Either String Int        parseEither c          | isDigit c = Right (digitToInt c)          | otherwise = Left "parse error">>> :}The following should work, since both @\'1\'@ and @\'2\'@ can beparsed as 'Int's.>>> :{    let parseMultiple :: Either String Int        parseMultiple = do          x <- parseEither '1'          y <- parseEither '2'          return (x + y)>>> :}>>> parseMultipleRight 3But the following should fail overall, since the first operation wherewe attempt to parse @\'m\'@ as an 'Int' will fail:>>> :{    let parseMultiple :: Either String Int        parseMultiple = do          x <- parseEither 'm'          y <- parseEither '2'          return (x + y)>>> :}>>> parseMultipleLeft "parse error"-}dataEitherab=Lefta|Rightbderiving(Eq-- ^ @since 2.01,Ord-- ^ @since 2.01,Read-- ^ @since 3.0,Show-- ^ @since 3.0)-- | @since 3.0instanceFunctor(Eithera)wherefmap_(Leftx)=Leftxfmapf(Righty)=Right(fy)-- | @since 4.9.0.0instanceSemigroup(Eitherab)whereLeft_<>b=ba<>_=a#if !defined(__HADDOCK_VERSION__)-- workaround https://github.com/haskell/haddock/issues/680stimesnx|n<=0=errorWithoutStackTrace"stimes: positive multiplier expected"|otherwise=x#endif-- | @since 3.0instanceApplicative(Eithere)wherepure=RightLefte<*>_=LefteRightf<*>r=fmapfr-- | @since 4.4.0.0instanceMonad(Eithere)whereLeftl>>=_=LeftlRightr>>=k=kr-- | Case analysis for the 'Either' type.-- If the value is @'Left' a@, apply the first function to @a@;-- if it is @'Right' b@, apply the second function to @b@.---- ==== __Examples__---- We create two values of type @'Either' 'String' 'Int'@, one using the-- 'Left' constructor and another using the 'Right' constructor. Then-- we apply \"either\" the 'length' function (if we have a 'String')-- or the \"times-two\" function (if we have an 'Int'):---- >>> let s = Left "foo" :: Either String Int-- >>> let n = Right 3 :: Either String Int-- >>> either length (*2) s-- 3-- >>> either length (*2) n-- 6--either::(a->c)->(b->c)->Eitherab->ceitherf_(Leftx)=fxeither_g(Righty)=gy-- | Extracts from a list of 'Either' all the 'Left' elements.-- All the 'Left' elements are extracted in order.---- ==== __Examples__---- Basic usage:---- >>> let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]-- >>> lefts list-- ["foo","bar","baz"]--lefts::[Eitherab]->[a]leftsx=[a|Lefta<-x]{-# INLINEABLElefts#-}-- otherwise doesnt get an unfolding, see #13689-- | Extracts from a list of 'Either' all the 'Right' elements.-- All the 'Right' elements are extracted in order.---- ==== __Examples__---- Basic usage:---- >>> let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]-- >>> rights list-- [3,7]--rights::[Eitherab]->[b]rightsx=[a|Righta<-x]{-# INLINEABLErights#-}-- otherwise doesnt get an unfolding, see #13689-- | Partitions a list of 'Either' into two lists.-- All the 'Left' elements are extracted, in order, to the first-- component of the output.  Similarly the 'Right' elements are extracted-- to the second component of the output.---- ==== __Examples__---- Basic usage:---- >>> let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]-- >>> partitionEithers list-- (["foo","bar","baz"],[3,7])---- The pair returned by @'partitionEithers' x@ should be the same-- pair as @('lefts' x, 'rights' x)@:---- >>> let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]-- >>> partitionEithers list == (lefts list, rights list)-- True--partitionEithers::[Eitherab]->([a],[b])partitionEithers=foldr(eitherleftright)([],[])wherelefta~(l,r)=(a:l,r)righta~(l,r)=(l,a:r)-- | Return `True` if the given value is a `Left`-value, `False` otherwise.---- @since 4.7.0.0---- ==== __Examples__---- Basic usage:---- >>> isLeft (Left "foo")-- True-- >>> isLeft (Right 3)-- False---- Assuming a 'Left' value signifies some sort of error, we can use-- 'isLeft' to write a very simple error-reporting function that does-- absolutely nothing in the case of success, and outputs \"ERROR\" if-- any error occurred.---- This example shows how 'isLeft' might be used to avoid pattern-- matching when one does not care about the value contained in the-- constructor:---- >>> import Control.Monad ( when )-- >>> let report e = when (isLeft e) $ putStrLn "ERROR"-- >>> report (Right 1)-- >>> report (Left "parse error")-- ERROR--isLeft::Eitherab->BoolisLeft(Left_)=TrueisLeft(Right_)=False-- | Return `True` if the given value is a `Right`-value, `False` otherwise.---- @since 4.7.0.0---- ==== __Examples__---- Basic usage:---- >>> isRight (Left "foo")-- False-- >>> isRight (Right 3)-- True---- Assuming a 'Left' value signifies some sort of error, we can use-- 'isRight' to write a very simple reporting function that only-- outputs \"SUCCESS\" when a computation has succeeded.---- This example shows how 'isRight' might be used to avoid pattern-- matching when one does not care about the value contained in the-- constructor:---- >>> import Control.Monad ( when )-- >>> let report e = when (isRight e) $ putStrLn "SUCCESS"-- >>> report (Left "parse error")-- >>> report (Right 1)-- SUCCESS--isRight::Eitherab->BoolisRight(Left_)=FalseisRight(Right_)=True-- | Return the contents of a 'Left'-value or a default value otherwise.---- @since 4.10.0.0---- ==== __Examples__---- Basic usage:---- >>> fromLeft 1 (Left 3)-- 3-- >>> fromLeft 1 (Right "foo")-- 1--fromLeft::a->Eitherab->afromLeft_(Lefta)=afromLefta_=a-- | Return the contents of a 'Right'-value or a default value otherwise.---- @since 4.10.0.0---- ==== __Examples__---- Basic usage:---- >>> fromRight 1 (Right 3)-- 3-- >>> fromRight 1 (Left "foo")-- 1--fromRight::b->Eitherab->bfromRight_(Rightb)=bfromRightb_=b{-{--------------------------------------------------------------------  Testing--------------------------------------------------------------------}prop_partitionEithers :: [Either Int Int] -> Boolprop_partitionEithers x =  partitionEithers x == (lefts x, rights x)-}

[8]ページ先頭

©2009-2025 Movatter.jp