Проверка на определенный конструктор данных - PullRequest
14 голосов
/ 22 мая 2011

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

data MyData = A arg| B arg2| C arg3

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

Ответы [ 3 ]

19 голосов
/ 22 мая 2011

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

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

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

isA (A _) = True
isA _     = False

isB (B _) = True
isB _     = False

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

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

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

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

Также обратите внимание: ваша декларация данных недействительна, имя должно быть заглавным, MyData вместо myData.

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

1 голос
/ 22 мая 2011

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

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

0 голосов
/ 08 июня 2019

Вы можете использовать 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
...