Проверка конкретного конструктора данных
Скажем, что я определил свой собственный тип данных типа
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