Вы разворачиваете значения из конструктора данных, используя сопоставление с шаблоном или определяя синтаксис записи (в этом случае Haskell сам генерирует геттеры).
Сопоставление с образцом
Так как здесь тип не определен как запись, нам, таким образом, необходимо использовать сопоставление с образцом:
getK :: Cmd -> Int
getK (PushK x) = x
-- ...
и, возможно, вам необходимо обработать случаидругой конструктор данных.
Мы также можем выполнить сопоставление этого шаблона с лямбда-выражением:
(\(PushK x) -> x) (PushK 5)
Записи
Мы также можем определить команду как запись:
data Cmd = PushK { k :: Int } | Pop | Push { p :: Int } deriving (Eq,Show)
Теперь Haskell автоматически сгенерировал две функции k :: Cmd -> Int
и p :: Cmd -> Int
, поэтому в этом случае мы можем написать:
k (PushK 5)
, который вернет 5
.
Почему (\_ x -> x) PushK 5
вернул 5
?
В Haskell функции граждан первого класса .Это означает, что вы можете передавать функции в качестве аргументов, возвращать их как результат.Вы здесь не создали Cmd
.
На самом деле PushK
- это конструктор данных , и функцию (с типом Int -> Cmd
), вытаким образом, называется лямбда-выражение с двумя параметрами: первое - pushK
, а второе - 5
.Вы просто пропускаете первый параметр и повторно вводите второй x
.
Но он, таким образом, выводится как:
(\y x -> x) PushK 5
= ((\y -> (\x -> x)) PushK) 5 -- (more verbose version)
-> (\x -> x) 5
-> 5