Data.Either
| Авторские права | (c) Университет Глазго 2001 |
|---|---|
| Лицензия | BSD-стиль (см. файл libraries/base/LICENSE) |
| Поддержка | libraries@haskell.org |
| Стабильность | экспериментальная |
| Переносимость | переносимая |
| Безопасный Haskell | Надежный |
| Язык | Haskell2010 |
Описание
Тип Either и связанные с ним операции.
data Either a b Исходный код
Тип Either представляет значения с двумя возможностями: значение типа Either a b является либо Left a, либо Right b.
Тип Either иногда используется для представления значения, которое либо правильное, либо ошибка; по соглашению, конструктор Left используется для хранения значения ошибки, а конструктор Right используется для хранения правильного значения (мнемоника: "right" также означает "правильный").
Примеры
Тип Either String Int — это тип значений, которые могут быть либо String, либо Int. Конструктор Left может быть использован только с String, а конструктор Right — только с Int:
>>> let s = Left "foo" :: Either String Int >>> s Left "foo" >>> let n = Right 3 :: Either String Int >>> n Right 3 >>> :type s s :: Either String Int >>> :type n n :: Either String Int
Функция fmap из нашего экземпляра Functor проигнорирует значения Left, но применит заданную функцию к значениям, содержащимся в Right:
>>> let s = Left "foo" :: Either String Int >>> let n = Right 3 :: Either String Int >>> fmap (*2) s Left "foo" >>> fmap (*2) n Right 6
Экземпляр Monad для Either позволяет нам объединить несколько действий, которые могут завершиться ошибкой, и завершить работу с ошибкой, если любое из отдельных шагов завершилось ошибкой. Сначала напишем функцию, которая может либо разобрать Int из Char, либо завершиться ошибкой.
>>> import Data.Char ( digitToInt, isDigit )
>>> :{
let parseEither :: Char -> Either String Int
parseEither c
| isDigit c = Right (digitToInt c)
| otherwise = Left "parse error"
>>> :}
Следующее должно сработать, так как как '1' и '2' могут быть обработаны как Int.
>>> :{
let parseMultiple :: Either String Int
parseMultiple = do
x <- parseEither '1'
y <- parseEither '2'
return (x + y)
>>> :}
>>> parseMultiple Right 3
Но следующее должно завершиться ошибкой, так как первое действие, в котором мы пытаемся разобрать 'm' как Int завершится ошибкой:
>>> :{
let parseMultiple :: Either String Int
parseMultiple = do
x <- parseEither 'm'
y <- parseEither '2'
return (x + y)
>>> :}
>>> parseMultiple Left "parse error"
Экземпляры
| Show2 Either | С версии: base-4.9.0.0 |
Определено в Data.Functor.Classes | |
| Read2 Either | С версии: base-4.9.0.0 |
Определено в Data.Functor.Classes МетодыliftReadsPrec2 :: (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] -> Int -> ReadS (Either a b) Источник liftReadList2 :: (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] -> ReadS [Either a b] Источник liftReadPrec2 :: ReadPrec a -> ReadPrec [a] -> ReadPrec b -> ReadPrec [b] -> ReadPrec (Either a b) Источник liftReadListPrec2 :: ReadPrec a -> ReadPrec [a] -> ReadPrec b -> ReadPrec [b] -> ReadPrec [Either a b] Источник | |
| Ord2 Either | С версии: base-4.9.0.0 |
Определено в Data.Functor.Classes | |
| Eq2 Either | С версии: base-4.9.0.0 |
| Bifunctor Either | С версии: base-4.8.0.0 |
| Bifoldable Either | С версии: base-4.10.0.0 |
Определено в Data.Bifoldable | |
| Bitraversable Either | Since: base-4.10.0.0 |
Определено в Data.Bitraversable Методыbitraverse :: Applicative f => (a -> f c) -> (b -> f d) -> Either a b -> f (Either c d) Источник | |
| Monad (Either e) | Since: base-4.4.0.0 |
| Functor (Either a) | Since: base-3.0 |
| MonadFix (Either e) | Since: base-4.3.0.0 |
Определено в Control.Monad.Fix | |
| Applicative (Either e) | Since: base-3.0 |
Определено в Data.Either | |
| Foldable (Either a) | Since: base-4.7.0.0 |
Определено в Data.Foldable Методыfold :: Monoid m => Either a m -> m Исходный код foldMap :: Monoid m => (a0 -> m) -> Either a a0 -> m Исходный код foldMap' :: Monoid m => (a0 -> m) -> Either a a0 -> m Исходный код foldr :: (a0 -> b -> b) -> b -> Either a a0 -> b Исходный код foldr' :: (a0 -> b -> b) -> b -> Either a a0 -> b Исходный код foldl :: (b -> a0 -> b) -> b -> Either a a0 -> b Исходный код foldl' :: (b -> a0 -> b) -> b -> Either a a0 -> b Исходный код foldr1 :: (a0 -> a0 -> a0) -> Either a a0 -> a0 Исходный код foldl1 :: (a0 -> a0 -> a0) -> Either a a0 -> a0 Исходный код toList :: Either a a0 -> [a0] Исходный код null :: Either a a0 -> Bool Исходный код length :: Either a a0 -> Int Исходный код elem :: Eq a0 => a0 -> Either a a0 -> Bool Исходный код maximum :: Ord a0 => Either a a0 -> a0 Исходный код minimum :: Ord a0 => Either a a0 -> a0 Исходный код sum :: Num a0 => Either a a0 -> a0 Исходный код product :: Num a0 => Either a a0 -> a0 Исходный код | |
| Traversable (Either a) | С момента: base-4.7.0.0 |
Определено в Data.Traversable Методыtraverse :: Applicative f => (a0 -> f b) -> Either a a0 -> f (Either a b) Исходный код sequenceA :: Applicative f => Either a (f a0) -> f (Either a a0) Исходный код mapM :: Monad m => (a0 -> m b) -> Either a a0 -> m (Either a b) Исходный код sequence :: Monad m => Either a (m a0) -> m (Either a a0) Исходный код | |
| Show a => Show1 (Either a) | С момента: base-4.9.0.0 |
Определено в Data.Functor.Classes МетодыliftShowsPrec :: (Int -> a0 -> ShowS) -> ([a0] -> ShowS) -> Int -> Either a a0 -> ShowS Исходный код liftShowList :: (Int -> a0 -> ShowS) -> ([a0] -> ShowS) -> [Either a a0] -> ShowS Исходный код | |
| Read a => Read1 (Either a) | С момента: base-4.9.0.0 |
Определено в Data.Functor.Classes МетодыliftReadsPrec :: (Int -> ReadS a0) -> ReadS [a0] -> Int -> ReadS (Either a a0) Исходный код liftReadList :: (Int -> ReadS a0) -> ReadS [a0] -> ReadS [Either a a0] Исходный код liftReadPrec :: ReadPrec a0 -> ReadPrec [a0] -> ReadPrec (Either a a0) Исходный код liftReadListPrec :: ReadPrec a0 -> ReadPrec [a0] -> ReadPrec [Either a a0] Исходный код | |
| Ord a => Ord1 (Either a) | С момента: base-4.9.0.0 |
Определено в Data.Functor.Classes МетодыliftCompare :: (a0 -> b -> Ordering) -> Either a a0 -> Either a b -> Ordering Исходный код | |
| Eq a => Eq1 (Either a) | С момента: base-4.9.0.0 |
Определено в Data.Functor.Classes | |
| Generic1 (Either a :: Type -> Type) | С момента: base-4.6.0.0 |
Определено в GHC.Generics Связанные типыtype Rep1 (Either a) :: k -> Type Исходный код Методыfrom1 :: forall (a0 :: k). Either a a0 -> Rep1 (Either a) a0 Исходный код to1 :: forall (a0 :: k). Rep1 (Either a) a0 -> Either a a0 Исходный код | |
| (Eq a, Eq b) => Eq (Either a b) | С момента: base-2.1 |
Определено в Data.Either Методы(==) :: Either a b -> Either a b -> Bool Исходный код (/=) :: Either a b -> Either a b -> Bool Исходный код | |
| (Data a, Data b) => Data (Either a b) | С момента: base-4.0.0.0 |
Определено в Data.Data Методыgfoldl :: (forall d b0. Data d => c (d -> b0) -> d -> c b0) -> (forall g. g -> c g) -> Either a b -> c (Either a b) Исходный код gunfold :: (forall b0 r. Data b0 => c (b0 -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Either a b) Исходный код toConstr :: Either a b -> Constr Исходный код dataTypeOf :: Either a b -> DataType Исходный код dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Either a b)) Исходный код dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Either a b)) Исходный код gmapT :: (forall b0. Data b0 => b0 -> b0) -> Either a b -> Either a b Исходный код gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Either a b -> r Исходный код gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Either a b -> r Исходный код gmapQ :: (forall d. Data d => d -> u) -> Either a b -> [u] Исходный код gmapQi :: Int -> (forall d. Data d => d -> u) -> Either a b -> u Исходный код gmapM :: Monad m => (forall d. Data d => d -> m d) -> Either a b -> m (Either a b) Исходный код gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Either a b -> m (Either a b) Исходный код gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Either a b -> m (Either a b) Исходный код | |
| (Ord a, Ord b) => Ord (Either a b) | Since: base-2.1 |
Определено в Data.Either Методыcompare :: Either a b -> Either a b -> Ordering Исходный код (<) :: Either a b -> Either a b -> Bool Исходный код (<=) :: Either a b -> Either a b -> Bool Исходный код (>) :: Either a b -> Either a b -> Bool Исходный код (>=) :: Either a b -> Either a b -> Bool Исходный код max :: Either a b -> Either a b -> Either a b Исходный код min :: Either a b -> Either a b -> Either a b Исходный код | |
| (Read a, Read b) => Read (Either a b) | Since: base-3.0 |
Определено в GHC.Generics type Rep (Either a b) = D1 ('MetaData "Either" "Data.Either" "base" 'False) (C1 ('MetaCons "Left" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 a)) :+: C1 ('MetaCons "Right" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 b))) |
either :: (a -> c) -> (b -> c) -> Either a b -> c Источник
Анализ вариантов для типа Either. Если значение Left a, примените первую функцию к a; если оно Right b, примените вторую функцию к b.
Примеры
Создаём два значения типа Either String Int, одно с использованием конструктора Left, а другое — с Right. Затем применяем функцию «either» к функции length (если у нас String) или функции «удваивания» (если у нас 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
lefts :: [Either a b] -> [a] Источник
Извлекает из списка Either все элементы Left. Все элементы Left извлекаются в порядке их следования.
Примеры
Базовое использование:
>>> let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ] >>> lefts list ["foo","bar","baz"]
rights :: [Either a b] -> [b] Источник
Извлекает из списка Either все элементы Right. Все элементы Right извлекаются в порядке их следования.
Примеры
Базовое использование:
>>> let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ] >>> rights list [3,7]
isLeft :: Either a b -> Bool Источник
Возвращает True если данное значение является значением Left, False в противном случае.
Примеры
Базовое использование:
>>> isLeft (Left "foo") True >>> isLeft (Right 3) False
Предполагая, что значение Left обозначает некоторую ошибку, мы можем использовать isLeft для написания очень простой функции обработки ошибок, которая ничего не делает в случае успеха и выводит «ОШИБКА», если произошла ошибка.
Этот пример демонстрирует, как isLeft может быть использован для избежания сопоставления с образцом, когда значение, содержащееся в конструкторе, не интересует:
>>> import Control.Monad ( when ) >>> let report e = when (isLeft e) $ putStrLn "ERROR" >>> report (Right 1) >>> report (Left "parse error") ERROR
С версии: base-4.7.0.0
isRight :: Either a b -> Bool Источник
Возвращает True если данное значение является значением Right, False в противном случае.
Примеры
Базовое использование:
>>> isRight (Left "foo") False >>> isRight (Right 3) True
Предполагая, что значение Left обозначает некоторую ошибку, мы можем использовать isRight для написания очень простой функции отображения, которая выводит только «УСПЕХ», когда вычисление выполнено успешно.
Этот пример демонстрирует, как isRight может быть использован для избежания сопоставления с образцом, когда значение, содержащееся в конструкторе, не интересует:
>>> import Control.Monad ( when ) >>> let report e = when (isRight e) $ putStrLn "SUCCESS" >>> report (Left "parse error") >>> report (Right 1) SUCCESS
С версии: base-4.7.0.0
fromLeft :: a -> Either a b -> a Источник
Возвращает содержимое значения Left или значение по умолчанию в противном случае.
Примеры
Базовое использование:
>>> fromLeft 1 (Left 3) 3 >>> fromLeft 1 (Right "foo") 1
С версии: base-4.10.0.0
fromRight :: b -> Either a b -> b Источник
Возвращает содержимое значения Right или значение по умолчанию в противном случае.
Примеры
Базовое использование:
>>> fromRight 1 (Right 3) 3 >>> fromRight 1 (Left "foo") 1
С версии: base-4.10.0.0
partitionEithers :: [Either a b] -> ([a], [b]) Источник
Разделяет список Either на два списка. Все элементы Left извлекаются в первом компоненте результата. Аналогично, элементы Right извлекаются во втором компоненте результата.
Примеры
Базовое использование:
>>> let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ] >>> partitionEithers list (["foo","bar","baz"],[3,7])
Пара, возвращаемая partitionEithers x, должна быть такой же, как у (lefts x, rights x):
>>> let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ] >>> partitionEithers list == (lefts list, rights list) True
© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/8.10.2/docs/html/libraries/base-4.14.1.0/Data-Either.html