【发布时间】:2016-04-06 08:29:24
【问题描述】:
GHC 在我的一些类成员的默认实现中不解析/传播约束。这种行为真的很奇怪,在我看来这是一个错误。
有人可以帮助我/向我解释发生了什么问题吗?
- 如何告诉 GHC 统一类声明中的
a和类方法中的a以便定义不模糊 - 有什么我不明白的地方吗?
代码:
module Foo where
import Data.Proxy
data Stuff a = Stuff
{content :: String}
class HasStuff a where
stuff :: Stuff a
-- This works
useStuffOK :: Proxy a -> (Stuff a)
useStuffOK _ = (stuff)
-- those don't work,
-- (but I think ghc has all the information necessary to figure it out)
useStuffBAD :: Proxy a -> (Stuff a, String)
useStuffBAD _ = (stuff, content (stuff :: Stuff a))
-- Could not deduce (HasStuff a1) arising from a use of ‘stuff’
-- from the context (HasStuff a)
-- bound by the class declaration for ‘HasStuff’
-- at Test.hs:(7,1)-(17,45)
useStuffBAD2 :: Proxy a -> String
useStuffBAD2 _ = content (stuff :: Stuff a)
-- Could not deduce (HasStuff a1) arising from a use of ‘stuff’
-- from the context (HasStuff a)
-- bound by the class declaration for ‘HasStuff’
-- at Test.hs:(7,1)-(17,45)
instance HasStuff Int where
stuff = Stuff "ok"
-- inference works here
x :: Stuff Int
x = stuff
-- works here too
x :: String
x = content (stuff :: Stuff Int)
谢谢
【问题讨论】:
-
这不是错误。
useStuffBAD _ = let x = stuff in (x, content x)和useStuffBAD2 = content . useStuffOK。那里的类型确实是模棱两可的——你可以在任何一个表达式中引用任何stuff。useStuffOK有效,因为输出类型由类型签名给出。由于content :: Stuff a -> String没有在结果中提及a类型,因此如果没有明确给出类型或无法从上下文中推断出类型,则此函数的使用是不明确的。 -
@user2407038 刚刚编辑了我的问题:当我明确给出类型时,它也不起作用,因为 ghc 没有统一类声明中的
a和类中的a方法。就我而言, useStuffBAD 明确说明了它应该选择什么实例。我仍然觉得这是 ghc 中的一个问题。 -
我认为您可能需要在文件顶部使用
{-# LANGUAGE ScopedTypeVariables #-}才能使其正常工作 - ghc 本身并不知道来自(Stuff a, String)的Stuff a与stuff :: Stuff a相同跨度> -
@Ravion 更新中的代码compiles(至少在 7.10.3 上)只有
ScopedTypeVariables,所以您要么实际上没有启用,要么您使用的是旧版本实际上可能有一个错误。 -
@user2407038 你是对的,我的错!
标签: haskell ghc typeclass inference unification