Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell GHC 7.7中引入的自由覆盖条件破坏了GHC 7.6中的有效代码_Haskell_Ghc_Type Inference_Typeclass_Typechecking - Fatal编程技术网

Haskell GHC 7.7中引入的自由覆盖条件破坏了GHC 7.6中的有效代码

Haskell GHC 7.7中引入的自由覆盖条件破坏了GHC 7.6中的有效代码,haskell,ghc,type-inference,typeclass,typechecking,Haskell,Ghc,Type Inference,Typeclass,Typechecking,想法 我正在写一本汇编成Haskell的书 这种语言的用户可以定义自己的不可变数据结构和相关函数。所谓关联函数,我指的是一个函数,它属于一个数据结构。 例如,用户可以编写(在“pythonic”伪代码中): (这相当于下面的代码,但也表明关联函数类似于开放世界假设的类型类): 在此示例中,method1是与Vector数据类型相关联的函数,可以像v.testid(5)一样使用(其中v是Vector数据类型的实例) 我正在将这样的代码翻译成Haskell代码,但我面临着一个问题,我一直在努力解决这

想法

我正在写一本汇编成Haskell的书

这种语言的用户可以定义自己的不可变数据结构和相关函数。所谓关联函数,我指的是一个函数,它属于一个数据结构。 例如,用户可以编写(在“pythonic”伪代码中):

(这相当于下面的代码,但也表明关联函数类似于开放世界假设的类型类):

在此示例中,
method1
是与
Vector
数据类型相关联的函数,可以像
v.testid(5)
一样使用(其中
v
Vector
数据类型的实例)

我正在将这样的代码翻译成Haskell代码,但我面临着一个问题,我一直在努力解决这个问题

问题

我正在尝试将代码从GHC7.6移到另一个版本(可以编译更新的版本)。该代码在GHC 7.6下运行良好,但在GHC 7.7下无法运行。 我想问你如何修复它,使它在新版本的编译器中工作

示例代码

让我们看看(由我的编译器)生成的Haskell代码的简化版本:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}

import Data.Tuple.OneTuple

------------------------------
-- data types
------------------------------
data Vector a = Vector {x :: a, y :: a, z :: a} deriving (Show)
-- the Vector_testid is used as wrapper over a function "testid". 
newtype Vector_testid a = Vector_testid a

------------------------------
-- sample function, which is associated to data type Vector
------------------------------
testid (v :: Vector a) x = x

------------------------------
-- problematic function (described later)
------------------------------
testx x = call (method1 x) $ OneTuple "test"

------------------------------
-- type classes
------------------------------
-- type class used to access "method1" associated function
class Method1 cls m func | cls -> m, cls -> func where 
    method1 :: cls -> m func

-- simplified version of type class used to "evaluate" functions based on 
-- their input. For example: passing empty tuple as first argument of `call` 
-- indicates evaluating function with default arguments (in this example 
-- the mechanism of getting default arguments is not available)
class Call a b where
    call :: a -> b

------------------------------
-- type classes instances
------------------------------
instance (out ~ (t1->t1)) => Method1 (Vector a) Vector_testid out where
  method1 = (Vector_testid . testid)

instance (base ~ (OneTuple t1 -> t2)) => Call (Vector_testid base) (OneTuple t1 -> t2) where
    call (Vector_testid val) = val

------------------------------
-- example usage
------------------------------
main = do
    let v = Vector (1::Int) (2::Int) (3::Int)
    -- following lines equals to a pseudocode of ` v.method1 "test" `
    -- OneTuple is used to indicate, that we are passing single element.
    -- In case of more or less elements, ordinary tuples would be used.
    print $ call (method1 v) $ OneTuple "test"
    print $ testx v
该代码可以编译并与GHC 7.6配合使用。当我试图用GHC 7.7编译它时,我得到以下错误:

debug.hs:61:10:
    Illegal instance declaration for
      ‛Method1 (Vector a) Vector_testid out’
      The liberal coverage condition fails in class ‛Method1’
        for functional dependency: ‛cls -> func’
      Reason: lhs type ‛Vector a’ does not determine rhs type ‛out’
    In the instance declaration for
      ‛Method1 (Vector a) Vector_testid out’
这个错误是由检查函数依赖项可以做什么的新规则引起的,即
自由覆盖条件
(据我所知,这是
覆盖条件
,通过使用
-xundecidedicatableinstances
而放松的)

一些尝试解决问题

我试图通过将
Method1
的定义更改为:

class Method1 cls m func | cls -> m where 
    method1 :: cls -> m func
这解决了函数依赖性的问题,但行:

testx x = call (method1 x) $ OneTuple "test"
不再允许,导致编译错误(在7.6和7.7版本中):

编辑:

使用类型族也不可能解决此问题(据我所知)。如果我们将
Method1
类型类和实例替换为以下代码(或similar):

我们会得到明显的错误
不在范围内:类型变量“t1”
,因为类型族不允许使用类型,这不会出现在类型表达式的LHS上

最后一个问题

在GHC 7.7下,我如何使这个想法起作用?我知道新的
自由覆盖条件
允许GHC开发人员在类型检查方面取得一些进展,但在GHC 7.6版本的编译器上移植idea应该是可行的


(在不强迫我的DSL用户引入任何进一步的类型的情况下——到目前为止的一切,比如类型类实例,我使用的是模板Haskell)

这不是GHC 7.7中的错误。当GHC允许实例时,这是一个长期存在的错误 这违反了函数依赖关系。幸运的是,这个问题似乎终于得到了解决。GHC 7.7发出的错误消息非常详细,指出了实例
Method1(Vector a)Vector\u testid的问题。回想一下功能语法的含义
依赖关系。给定

  class C a b | a -> b
因此,如果类型
a
b
b1
cab
cab1
两者都成立,
b
b1
必须是相同的。让我们看看您的实例:

  Method1 (Vector a) Vector_testid (t1->t1)
如果我们的类型
b
b1
满足
Method1(Vector Int)Vector\u testid(b->b)
Method1(Vector a)Vector\u testid(b1->b1)
,这并不意味着
b
b1
必须相同。因此,你的例子是错误的。GHC 7.6和之前接受该程序的事实是GHC中众所周知的错误(每年都会讨论)

你似乎在试图定义这样的东西

 Method1 (Vector a) Vector_testid (forall t. t -> t)
唉,尽管存在许多工作区,但这种语法是不允许的。例如,其中一个涉及Apply类(例如,参见HList文章)。一个简单的方法如下

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}

-- import Data.Tuple.OneTuple
newtype OneTuple x = OneTuple x deriving Show

------------------------------
-- data types
------------------------------
data Vector a = Vector {x :: a, y :: a, z :: a} deriving (Show)

-- testx x = call (method1 x) $ OneTuple "test"
testx x = call x Method1 $ OneTuple "test"

-- associate methods to classes
class Methods cls m x y | cls m x -> y where
  call :: cls -> m -> x -> y

instance Methods (Vector a) Method1 x x where
  call self _ x = x

data Method1 = Method1 -- method label

你可以写一个bug报告,你可以尝试使用类型族而不是函数依赖关系。我在GHC 7.7上查不到,但是ot看起来你可以去掉
(out~(t1->t1))
部分,把一个实例重写成
实例方法1(Vector a)Vector\u testid(t->t)
@wit:当然可以,但它并没有改变任何东西:(错误仍然是一样的,并且仍然不满足
自由覆盖条件
。@viorior:我已经添加了“编辑”部分,请查看。我看不到使用类型族来解决此问题的方法。您有其他想法吗?如果我没有找到任何解决方案,我当然会将此报告为错误。
  class C a b | a -> b
  Method1 (Vector a) Vector_testid (t1->t1)
 Method1 (Vector a) Vector_testid (forall t. t -> t)
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}

-- import Data.Tuple.OneTuple
newtype OneTuple x = OneTuple x deriving Show

------------------------------
-- data types
------------------------------
data Vector a = Vector {x :: a, y :: a, z :: a} deriving (Show)

-- testx x = call (method1 x) $ OneTuple "test"
testx x = call x Method1 $ OneTuple "test"

-- associate methods to classes
class Methods cls m x y | cls m x -> y where
  call :: cls -> m -> x -> y

instance Methods (Vector a) Method1 x x where
  call self _ x = x

data Method1 = Method1 -- method label