1

给定以下代码,forall a r从失败类型中删除go“Typeable (D r) 的重叠实例”。我想知道为什么?

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
module M where

import Data.Typeable (Proxy, Typeable, cast)

class C r where
    data D r :: *

deriving instance Typeable D

data A = forall r . A (D r)

go :: forall r a . (Typeable a, Typeable (D r)) => a -> Proxy r -> A
go a _ = case cast a of
  Just (b :: D r) -> A b
  Nothing -> error "fail to cast"

该错误还说“选择取决于”的实例化r-但这不是由提供的固定Proxy r吗?

4

1 回答 1

4

这就是作用域类型变量在 Haskell 中的工作方式。请注意,您在r此处重复使用:

go :: forall r a . (Typeable a, Typeable (D r)) => a -> Proxy r -> A
go a _ = case cast a of
  Just (b :: D r) -> A b  -- this r is the same as the r above

如果没有明确的forall,类型变量被解释为签名的本地变量。也就是说,您的代码被读取为:

go :: (Typeable a1, Typeable (D r1)) => a1 -> Proxy r1 -> A  -- renaming local variables
go a _ = case cast a of
  Just (b :: D r) -> A b   -- r bears no relation to r1

因此类型错误。

(不过,出现错误会令人困惑Overlapping instances。)

于 2015-06-29T11:54:44.177 回答