【问题标题】:Haskell Inferred/Explicit Types of Where BindingsHaskell 推断/显式 Where 绑定类型
【发布时间】:2015-02-27 07:57:18
【问题描述】:

我正在尝试编写一个函数来比较两个给定图表中节点的度数列表,以进行同构的充分性测试,但我注意到以下代码引发了与 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 时期待Graph a 而不是Graph b。当然,有一个简单的解决方案

isoByDegree g1 g2 = (sort . degreeNumbers) g1 == (sort . degreeNumbers) g2

但我想知道绑定方法出了什么问题。

【问题讨论】:

  • 这些 MR 问题在这里如此频繁地出现在 SO 上,我认为 GHC 至少应该默认警告它们(假设默认关闭 MR 是不可取的)。例如。对于类型错误,如果表达式包含一些单态推断的术语,GHC 应该输出关于它们的警告。

标签: haskell types


【解决方案1】:

这是由可怕的monomorphism restriction 引起的。使用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

如果你不想禁用单态限制,你可以给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 声明多态。

【讨论】:

  • 谢谢,这两种解决方案都很有见地。就在我以为自己会遇到基本应用程序领域中所有晦涩难懂的绊脚石的时候!
【解决方案2】:

因为您在等式的右侧而不是左侧给出类型声明,所以 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

【讨论】:

    猜你喜欢
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多