如何为Haskell函数传递类型提示以验证枚举实现正确性?
验证自定义Enum类型的第二个等式
要验证 (fromEnum . toEnum) z = z(其中z是对应Colour枚举的合法Int值),核心是让编译器明确toEnum的目标转换类型为Colour,以下是几种实用解决方案:
1. 给验证函数内的toEnum加类型注解
直接针对Colour写验证函数,通过类型标注指定toEnum的目标类型:
convertsToFrom :: Int -> Bool convertsToFrom z = fromEnum (toEnum z :: Colour) == z
调用合法值即可验证:
convertsToFrom 0 -- 返回True convertsToFrom 1 -- 返回True convertsToFrom 2 -- 返回True
2. 实现通用验证函数(借助ScopedTypeVariables)
如果需要让验证函数适配任意Enum类型,可启用ScopedTypeVariables扩展,通过类型参数指定目标枚举类型:
{-# LANGUAGE ScopedTypeVariables #-} convertsToFrom :: forall a. (Enum a, Eq Int) => Int -> Bool convertsToFrom z = fromEnum (toEnum z :: a) == z
调用时用类型应用指定要验证的枚举类型(GHC 8.0+支持):
convertsToFrom @Colour 0 -- 返回True convertsToFrom @Colour 1 -- 返回True
3. 用QuickCheck自动化批量验证
若要批量验证所有合法值,推荐用QuickCheck生成测试用例,仅针对0-2范围内的Int值验证:
import Test.QuickCheck -- 定义验证属性:仅当z是Colour的合法枚举值时,等式成立 prop_toFromColour :: Int -> Property prop_toFromColour z = z `elem` [0,1,2] ==> fromEnum (toEnum z :: Colour) == z
在GHCi中执行测试:
quickCheck prop_toFromColour -- 输出+++ OK, passed 100 tests.
额外优化提示
当前Colour的Enum实现未处理超出0-2的Int值,调用toEnum 3会触发运行时错误。若需要更健壮的实现,可修改toEnum返回Maybe Colour或给出明确错误:
instance Enum Colour where fromEnum Red = 0 fromEnum Green = 1 fromEnum Blue = 2 toEnum 0 = Red toEnum 1 = Green toEnum 2 = Blue toEnum n = error $ "无效的Colour枚举值: " ++ show n
内容的提问来源于stack exchange,提问作者Rik
相关产品推荐
相关产品推荐

