我有:
infixr 9 |||
data a ||| b = A a|B b deriving (Eq, Data, Show)
class IsTag a where
anyTag :: a
并且我保留了a|||b
这些IsTag
的实例值,例如:A (B (A x))
- 嵌套的深度可以是任何肯定的。我想编写一个函数来检测x
等于anyTag
,所以它需要a|||b
并返回Bool
- 是基础值(x
例子)等于x实例的anyTag
。怎么写这样的功能?由于“无限类型”等错误,我无法进行模式匹配。我将deriving Data
添加到a|||b
和x的类型,希望可以使用{{{{{ 1}},但我无法理解如何通过这种递归类型进行折叠/遍历。
答案 0 :(得分:2)
它不会比这更好:
{-# LANGUAGE DefaultSignatures #-}
class IsAnyTag a where
isAnyTag :: a -> Bool
default isAnyTag :: (Eq a, IsTag a) => a -> Bool
isAnyTag = (anyTag ==)
instance (IsAnyTag a, IsAnyTag b) => IsAnyTag (a ||| b) where
isAnyTag (A a) = isAnyTag a
isAnyTag (B b) = isAnyTag b
-- and one more line of `instance IsAnyTag X` for each `X` that
-- is an instance of `IsTag`
这里的主要缺点是,即使您只测试一方,这也要求|||
两侧的类型必须是IsAnyTag
个实例。他们是静态类型检查的中断。