Haskell中(:==)的类型签名无效问题求助
关于Haskell中
(:==)类型签名无效错误的成因解析 嘿,这个问题我之前帮不少Haskell开发者排查过,咱们一步步拆解为啥会出现这个错误:
冒号开头的运算符有特殊规则
Haskell里有个硬性规则:所有以冒号:开头的中缀运算符,默认被编译器识别为代数数据类型的构造器,而不是普通的函数。普通函数的类型签名写法和数据构造器完全不一样——数据构造器必须属于某个data或newtype的定义,不能像普通函数那样直接单独定义类型签名和实现。举个反例,如果你写了这样的代码:
(:==) :: Int -> Int -> Bool a :== b = a == b编译器立刻会报错,因为它把
(:==)当成了数据构造器,但你却给它套了普通函数的类型签名,完全不符合数据构造器的定义规范。混淆了数据构造器和普通运算符的定义逻辑
如果你确实想用(:==)这个符号,有两种合法的方式:- 把它改成普通运算符:把开头的冒号去掉,比如换成
(===),这样就能像普通函数一样定义类型签名和实现了; - 把它定义成数据构造器:必须把它放在某个代数数据类型的定义里,比如:
这时候data Equality a = a :== a deriving (Show)(:==)的类型是a -> a -> Equality a,是完全合法的数据构造器写法,编译器不会报错。
- 把它改成普通运算符:把开头的冒号去掉,比如换成
罕见情况:类型签名的语法错误
当然也有可能是你在写类型签名时不小心犯了语法错误(比如漏写括号、写错类型变量),但针对(:==)这个符号,90%以上的概率都是上面说的“冒号开头运算符的特殊规则”导致的。
总结一下:核心问题就是你把Haskell中具有特殊身份的冒号开头运算符,当成了普通函数来定义,编译器的预期和你的写法不匹配,所以抛出了“类型签名无效”的错误。
内容的提问来源于stack exchange,提问作者Márton Kardos
相关产品推荐
相关产品推荐

