Я собираюсь начать с некоторых предположений:
- У вас есть тип
data Layer = ...
- У вас есть псевдоним типа
type Name = String
- Вы есть некоторая функция
layerName :: Layer -> Name
Я собираюсь пройтись по определению чистой функции не потому, что она ужасно важна, а потому, что она использует технику для перехода от чистого к нечистому (т.е. IO
-зависимый) код.
Имеет ли данный слой заданное имя?
Во-первых, у вас есть базовая операция
strcmp(layerName, layerProperties.layerName) == 0
Это простая Haskell функция, которая принимает Name
и Layer
и возвращает True
, если слой имеет заданное имя.
hasName :: Name -> Layer -> Bool
hasName name layer = name == layerName layer
Есть ли один из нескольких слоев, какой-либо один из нескольких имен?
Но у нас нет ни одного имени или слоя; у нас есть списки каждого. Мы можем легко справиться с этим, используя экземпляр Applicative
для списков для моделирования недетерминизма.
import Control.Applicative
foo :: [Name] -> [Layer] -> [Bool]
foo = liftA2 hasName
Я не буду беспокоиться о том, чтобы дать этой функции хорошее имя, потому что оно нам не понадобится.
Теперь мы можем получить список результатов сравнения каждого имени с каждым слоем, но мы не заботимся об отдельных результатах: мы просто хотим одно значение , которое говорит, нашли ли мы совпадение или нет. Для этого мы будем использовать or :: [Bool] -> Bool
.
findMatch :: [Name] -> [Layer] -> Bool
findMatch names layers = or (foo names layers)
foo
достаточно просто, чтобы мы просто включили его определение, чтобы нам не нужно было придумывать лучшее имя:
findMatch :: [Name] -> [Layer] -> Bool
findMatch names layers = or (liftA2 hasName names layers)
Обработка ввода-вывода
Теперь мы предполагаем, что у нас уже есть наши списки имен и слоев в качестве чистых значений. Но что если мы этого не сделаем? Что если у нас есть только списки, считанные из файла или из другого места, так что у нас есть IO [Name]
и / или IO [Layer]
? Решение состоит в том, чтобы снова использовать liftA2
, но вместо использования экземпляра списка Applicative
мы будем использовать экземпляр IO
.
ionames :: IO [Name]
ionames = ...
iolayers :: IO [Layer]
iolayers = ...
result :: IO Bool
result = liftA2 findMatch ionames iolayers