Определение типа алгебраической структуры данных

Предположим, data MyAlgebraicType :: Foo Int | Bar Int. Если у меня есть переменная типа MyAlgebraicType, как определить, является ли она типом Foo Int или Bar Int?


person cb7    schedule 20.10.2018    source источник
comment
Второстепенный момент: не называйте типы Foo Int и Bar Int, так как это не так. Здесь только MyAlgebraicType является типом. Обычно мы вызываем конструкторы Foo и Bar. Более неформально можно спросить, как определить форму значения в алгебраическом (данные) типе?   -  person chi    schedule 20.10.2018


Ответы (2)


Использование case:

let var = Bar 42 in
case var of
    Foo _ -> putStrLn "It's a Foo!"
    Bar _ -> putStrLn "It's a Bar!"

Эти _ можно заменить именем переменной, чтобы связать содержащееся Int.

Вы также можете использовать определение сопоставления с образцом (которое встречается чаще, чем case):

tellMeIt :: MyAlgebraicType -> IO ()
tellMeIt (Foo _) = putStrLn "It's a Foo!"
tellMeIt (Bar _) = putStrLn "It's a Bar!"
person luqui    schedule 20.10.2018

Сопоставление с образцом обычно лучше, но в некоторых случаях код может быть легче читать с помощью таких функций:

isFoo :: MyAlgebraicType -> Bool
isFoo (Foo _) = True
isFoo _       = False

isBar :: MyAlgebraicType -> Bool
isBar (Bar _) = True
isBar _       = False
person Chai T. Rex    schedule 20.10.2018
comment
Идиома: isBar x = is [ () | Bar{} <- [x] ] (где is = not . null). К сожалению, это очень шумная идиома. - person luqui; 20.10.2018