Как проверить, все ли элементы в списке одного алгебраического типа в Haskell? - PullRequest
4 голосов
/ 23 октября 2019

Если у меня следующий алгебраический тип данных

type MyVal = Either String Int

и у меня есть список, содержащий элемент типа MyVal

ls = [Right 1, Right 2, Right 3]
xs = [Right 1, Left "error", Right 3]

, я хочу, чтобы функция write выяснила, что это мой списокимея все значение 'Right', он должен вернуть True, иначе False.

В случае ls он вернет True, а для xs он вернет False.

Как я могу это сделать?

Я пытался использовать all функция, но не может использовать его правильно.

Ответы [ 2 ]

19 голосов
/ 23 октября 2019

Не говоря уже о all isRight в качестве хорошего ответа на заданный вопрос, я бы в некоторой степени задал вопрос. Что хорошего в том, чтобы вычислить, как Bool, все ли значения Either в списке Right? Что это позволяет вам делать? Один из ответов заключается в том, что он дает вам право исключать теги Right из всего списка, рассматривая все как свободные от ошибок.

Более информативным вариантом может быть создание чего-то типа

[Either String Int] -> Either String [Int]

, так что вместо простого True или False вы получите все Int s без тегов или сообщение, связанное с первым надоедливым Left.

И есть стандартная функция, котораяделает это (и многое другое кроме). Он использует тот факт, что списки представляют собой структуру данных со стандартным шаблоном обхода и что Either String кодирует понятие вычислений, управляющих ошибками, со стандартными шаблонами распространения сбоев и успешного распространения. Тип уже сделал тяжелую работу. Все, что вам нужно сказать, это ...

sequenceA
6 голосов
/ 23 октября 2019

Вы можете использовать функцию isRight :: Either a b -> Bool, чтобы проверить, является ли значение Either a b значением Right x.

Таким образом, вы можете реализовать этос:

import Data.Either(isRight)

allRight :: Foldable f => f (Either a b) -> Bool
allRight = all <b>isRight</b>

Это дает нам ожидаемый результат:

Prelude Data.Either> allRight ls
True
Prelude Data.Either> allRight xs
False
...