Проверка конкретного конструктора данных

Скажем, что я определил свой собственный тип данных типа

data MyData = A arg| B arg2| C arg3

Как написать функцию (например: isMyDataType), которая проверяет, имеет ли данный аргумент один из конкретных типов в MyData и последовательно возвращает логическое значение (True или False), например. набрав в Ghci: isMyDataType B возвращает значение True и isMyDataType Int возвращает False.

Ответы

Ответ 1

Я считаю, что вы хотите, чтобы функции проверялись для конкретных конструкторов :

isA :: MyData -> Bool
isB :: MyData -> Bool

Если да, тогда вы можете написать их самостоятельно или получить их. Реализация будет выглядеть так:

isA (A _) = True
isA _     = False

isB (B _) = True
isB _     = False

Чтобы получить их автоматически, просто используйте библиотеку derive и добавьте в исходный код:

{-# LANGUAGE TemplateHaskell #-}
import Data.DeriveTH

data MyData = ...
    deriving (Eq, Ord, Show}

derive makeIs ''MyData
-- Older GHCs require more syntax: $( derive makeIs ''MyData)

Также обратите внимание: объявление данных недопустимо, имя должно быть заглавным, MyData вместо MyData.

Наконец, весь этот ответ основан на предположении, что вы хотите проверить конструкторы, а не типы данных, как вы сказали (которые статически проверяются во время компиляции, как сказал Тарраш).

Ответ 2

Haskell всегда проверяет, что типы имеют смысл. Компилятор будет жаловаться сразу, если вы написали isMyDataType 4, потому что 4 не имеет тип MyData, это тип Int.

Я не уверен, что это то, о чем вы просили, но в любом случае я настоятельно рекомендую вам попробовать, что вы здесь задали на практике, чтобы вы могли убедиться сами. Самое главное, что вы проверяете подписи типа в haskell, это ключ к изучению haskell.

Ответ 3

Вы можете использовать Maybe с. Вы можете создать набор функций, которые проверяют для каждого из типов

getA, getB, getC :: MyData a -> Maybe a
getA x = case x of {(A v) -> Just v; _ -> Nothing}
getB x = case x of {(B v) -> Just v; _ -> Nothing}
getC x = case x of {(C v) -> Just v; _ -> Nothing}

Это дает некоторые практические идиомы для определенных задач:

allAs :: [MyData a] -> [a]
allAs xs = mapMaybe getA xs

printIfA :: Show a => MyData a -> IO ()
printIfA x = maybe (return ()) print $ getA x