Haskell中如何将字符与类型参数进行相等比较?
问题分析与解决
最小可复现示例(MRE)
data MRE a = Blah | Eh a | Umm (MRE a) (MRE a) deriving (Eq, Ord, Show) -- function: foo :: Eq a => Char -> MRE a -> Bool -- pattern match on Blah here -- foo x (Eh e) | x == e = True | otherwise = False
报错信息
Couldn't match expected type ‘Char’ with actual type ‘a’ ‘a’ is a rigid type variable bound by
修复方法(无需显式实现Eq实例)
错误根源是函数签名中a是任意满足Eq约束的类型,但代码里试图将Char类型的x与a类型的e做相等比较,类型不匹配。以下是几种修复方案:
方案1:限定a为Char类型
直接把类型参数a固定为Char,让两边比较的类型统一:
foo :: Char -> MRE Char -> Bool foo _ Blah = False -- 补充Blah分支的处理 foo x (Eh e) | x == e = True | otherwise = False foo x (Umm m1 m2) = foo x m1 || foo x m2 -- 可选:补充Umm分支的递归处理
方案2:传入类型转换函数
保留a的通用性,通过传入转换函数将a类型的值转为Char后再比较:
foo :: Eq a => (a -> Char) -> Char -> MRE a -> Bool foo _ _ Blah = False foo f x (Eh e) | x == f e = True | otherwise = False foo f x (Umm m1 m2) = foo f x m1 || foo f x m2
调用示例:foo id 'c' (Eh 'c')(针对Char类型),或foo (head . show) '1' (Eh 1)(针对数值类型)。
方案3:约束a可转换为Char
利用现有类型类(如Show)或自定义类型类,让a能安全转为Char:
foo :: (Eq a, Show a) => Char -> MRE a -> Bool foo _ Blah = False foo x (Eh e) | not (null (show e)) && x == head (show e) = True | otherwise = False foo x (Umm m1 m2) = foo x m1 || foo x m2
注:这里用show转换需处理空字符串的情况,更严谨的方式是自定义类型类实现安全转换。
方案4:调整逻辑适配类型
如果需求是判断Eh构造器的值是否和Char存在关联,可重构逻辑适配类型。比如当a为Maybe Char时:
foo :: Char -> MRE (Maybe Char) -> Bool foo _ Blah = False foo x (Eh (Just e)) = x == e foo _ (Eh Nothing) = False foo x (Umm m1 m2) = foo x m1 || foo x m2
内容的提问来源于stack exchange,提问作者kesarling
相关产品推荐
相关产品推荐

