Совпадение шаблона Haskell по типу
Есть ли способ сделать что-то подобное в haskell?
data Fruits = Apple Int | Orange Int deriving (Eq, Show)
basket = [Apple 2, Orange 4]
from_basket t (x:basket) =
case x of
(t i) -> i
_ -> from_basket t basket
Теперь я хочу получить "яблоко" из списка фруктов (корзины)
from_basket Apple basket
Без явного соответствия шаблону
case x of
Apple i -> ...
Orange i -> ...
_ ->
Ответы
Ответ 1
Одним из способов было бы определить вашу собственную вспомогательную функцию isApple
, а затем выполнить фильтрацию:
isApple (Apple _) = True
isApple _ = False
getApples = filter isApple
Сравнение шаблонов - это инструмент по вашему выбору, я не знаю, можно ли это упростить. Но, кроме некоторого грязного шаблона Haskell, я не вижу другого способа.
Ответ 2
Другие ответы объяснили, почему он не будет работать так, как есть, но, поскольку альтернативы идут, желание сделать что-то подобное часто является признаком того, что ваши типы данных должны выглядеть примерно так:
data FruitName = Apple | Orange deriving (Eq, Show)
data Fruits = Fruits FruitName Int deriving (Eq, Show)
... в этом случае искомая функция становится тривиальной.
Ответ 3
Вы можете сделать что-то подобное этому, определяя функции селектора
getApple :: Fruits -> Maybe Int
getApple (Apple x) = Just x
getApple _ = Nothing
getOrange :: Fruits -> Maybe Int
getOrange (Orange x) = Just x
getOrange _ = Nothing
fromBasket selector [] = Nothing
fromBasket selector (x:basket) =
case selector x of
Just x -> Just x
Nothing -> fromBasket selector basket
Теперь вы можете сделать
> fromBasket getApple basket
Just 2
> fromBasket getOrange basket
Just 4
Это предполагает, что ваши конструкторы принимают аналогичные аргументы. Он также возвращает Nothing
, если нужный тип плода не был в корзине.