Haskell推断/显式类型的Where绑定
我试图编写一个函数来比较两个给定图形中节点的度数列表,以进行同构的充分性测试,但我注意到以下代码抛出了与Haskell推断/显式类型的Where绑定,haskell,types,Haskell,Types,我试图编写一个函数来比较两个给定图形中节点的度数列表,以进行同构的充分性测试,但我注意到以下代码抛出了与degs类型相关的错误: import Data.List degreeNumbers :: (Eq a) => Graph a -> [Int] degreeNumbers g = ... isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool isoByDegree g1 g2 = degs g1
degs
类型相关的错误:
import Data.List
degreeNumbers :: (Eq a) => Graph a -> [Int]
degreeNumbers g = ...
isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool
isoByDegree g1 g2 = degs g1 == degs g2
where degs = sort . degreeNumbers
即使我试图用一个显式声明绑定degs
,比如
where degs = (sort . degreeNumbers) :: (Eq c) => Graph c -> [Int]
它仍然表示,在应用于g2
时,它期待的是一种图形a
而不是图形b
。当然,有一个简单的解决方案
isoByDegree g1 g2 = (sort . degreeNumbers) g1 == (sort . degreeNumbers) g2
但是我想知道绑定方法到底出了什么问题。这是由恐惧造成的。使用
NoMonomorphismRestriction
禁用它
{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.List
type Graph a = [a]
degreeNumbers :: (Eq a) => Graph a -> [Int]
degreeNumbers g = undefined
isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool
isoByDegree g1 g2 = degs g1 == degs g2
where degs = sort . degreeNumbers
如果不想禁用monomorhism限制,可以为degs
声明提供显式签名
isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool
isoByDegree g1 g2 = degs g1 == degs g2
where
degs :: (Eq c) => Graph c -> [Int]
degs = sort . degreeNumbers
在声明的右侧添加签名只会给右侧的表达式一个显式类型(这与推断的类型相同);它不会使
degs
声明多态。因为您将类型声明放在等式的右侧,而不是左侧,Haskell仍然使用类型推断来确定degs
的类型。由于单态性的限制,它只会推断出一个单态类型,而不是“看起来”像一个函数。解决方法是显式地注释您正在命名的对象,而不是为其名称指定值:
isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool
isoByDegree g1 g2 = degs g1 == degs g2
where degs :: (Eq c) => Graph c -> [Int]
degs = sort . degreeNumbers
谢谢,这两种解决方案都很有见地。就在我以为自己在我的基本应用程序领域遇到了所有难以捉摸的绊脚石的时候!这些MR问题在这里频繁出现,因此我认为GHC至少应该在默认情况下发出警告(假设默认情况下关闭MR是不可取的)。例如,对于类型错误,如果表达式包含一些单态推断项,GHC应输出有关这些项的警告。