Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.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 具有更高类型的GADT类型推理_Haskell_Ghc - Fatal编程技术网

Haskell 具有更高类型的GADT类型推理

Haskell 具有更高类型的GADT类型推理,haskell,ghc,Haskell,Ghc,我有一些代码可以编译: {-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs, FlexibleContexts #-} module Foo where data Foo :: (* -> *) where Foo :: c m zp' -> Foo (c m zp) f :: forall c m zp d . Foo (c m zp) -> d f y@(Foo (x :: c

我有一些代码可以编译:

{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs, 
             FlexibleContexts #-}

module Foo where

data Foo :: (* -> *) where
  Foo :: c m zp' -> Foo (c m zp)

f :: forall c m zp d . Foo (c m zp) -> d
f y@(Foo (x :: c m a)) = g x y

g :: c m a -> Foo (c m b) -> d
g = error ""
{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs, 
             FlexibleContexts, PolyKinds #-}

module Foo where

data Foo :: (* -> *) where
  Foo :: (c :: k -> * -> *) m zp' -> Foo (c m zp)

f :: forall (c :: k -> * -> *) m zp d . Foo (c m zp) -> d
f y@(Foo x) = g x y

g :: c m a -> Foo (c m b) -> d
g = error ""
在我的真实代码中,我需要的关键是说服GHC,如果
y
的类型是
Foo(cmzp)
,而
x
的类型是
cmzp'
,那么
c'~c
m'~m
。上面的代码实现了这一点,因为我能够调用
g

我想用两种正交的方式修改这段代码,但我似乎不知道如何让GHC用这两种修改来编译代码

第一个更改:添加
-XPolyKinds
。GHC 7.8.3投诉:

Foo.hs:10:11:
    Could not deduce ((~) (k2 -> k3 -> *) c1 c)
    from the context ((~) * (c m zp) (c1 m1 zp1))
      bound by a pattern with constructor
                 Foo :: forall (k :: BOX)
                               (k :: BOX)
                               (c :: k -> k -> *)
                               (m :: k)
                               (zp' :: k)
                               (zp :: k).
                        c m zp' -> Foo (c m zp),
               in an equation for ‘f’
      at Foo.hs:10:6-21
      ‘c1’ is a rigid type variable bound by
           a pattern with constructor
             Foo :: forall (k :: BOX)
                           (k :: BOX)
                           (c :: k -> k -> *)
                           (m :: k)
                           (zp' :: k)
                           (zp :: k).
                    c m zp' -> Foo (c m zp),
           in an equation for ‘f’
           at Foo.hs:10:6
      ‘c’ is a rigid type variable bound by
          the type signature for f :: Foo (c m zp) -> d
          at Foo.hs:9:13
    Expected type: c1 m1 zp'
      Actual type: c m a
    Relevant bindings include
      y :: Foo (c m zp) (bound at Foo.hs:10:3)
      f :: Foo (c m zp) -> d (bound at Foo.hs:10:1)
    In the pattern: x :: c m a
    In the pattern: Foo (x :: c m a)
    In an equation for ‘f’: f y@(Foo (x :: c m a)) = g x y

Foo.hs:10:11:
    Could not deduce ((~) k2 m1 m)
    from the context ((~) * (c m zp) (c1 m1 zp1))
    ...
第二个变化:忘记
-XPolyKinds
。相反,我想使用
-XDataKinds
创建一个新的种类,并限制
m
的种类:

{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs, 
             FlexibleContexts, DataKinds #-}

module Foo where

data Bar

data Foo :: (* -> *) where
  Foo :: c (m :: Bar) zp' -> Foo (c m zp)

f :: forall c m zp d . Foo (c m zp) -> d
f y@(Foo (x :: c m a)) = g x y

g :: c m a -> Foo (c m b) -> d
g = error ""
我得到了类似的错误(
无法推断(c1~c)
无法推断(m1~m)
)。
datatypes
似乎与此相关:如果我限制
m
使用kind
Constraint
而不是kind
Bar
,则代码可以很好地编译


我给出了两个如何破坏原始代码的示例,这两个示例都使用了更高级的类型。我尝试过使用case语句而不是模式保护,尝试过给
节点指定类型而不是
x
,我通常的技巧在这里不起作用


我并不挑剔
x
的类型在哪里结束/它看起来是什么样子,我只需要说服GHC,如果
y
的类型是
Foo(cmzp)
,那么
x
的类型是
cmzp'
对于一些不相关的类型
zp'
,我将原来的问题大大简化为如下:,不使用
{-#LANGUAGE polyteches}
编译,但使用
polyteches
编译失败

{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs #-}
{-# LANGUAGE PolyKinds #-}

data Pair1 :: (* -> *) where
  Pair1 :: Pair1 (c a, c b)

data D p a where
    D :: p (a, b) -> D p a -> D p b

f :: forall c z. D Pair1 (c z) -> D Pair1 (c z)
f y@(D Pair1 x) |
    (_ :: D Pair1 (c z)) <- y,
    (_ :: D Pair1 (c z')) <- x = y
这个错误强烈地表明了我已经怀疑的,答案取决于是否。若多类类型的应用程序是内射的,我们可以推导出如下
c1~c

(a,   c z) ~ (c1 a1,   c1 b)
(a,) (c z) ~ (c1 a1,) (c1 b) {- switch to prefix notation -}
      c z  ~           c1 b  {- f a ~ g b implies a ~ b -}
      c    ~           c1    {- f a ~ g b implies f ~ g -}
      c1   ~           c     {- ~ is reflexive -}
,但ghc不知道。为了让ghc推断类型应用程序是内射的,我们需要提供种类签名,以便编译器知道种类是等价的


我还没有找到足够的注释来解释这个问题的原始、过于简化的版本。当简化处理类型的问题时,将类型简化为本质上的
代理
有时是过度的,因为这样可以减少附加类型签名的位置。你必须解决一个更有意义的问题。

这个问题可以通过添加种类签名来解决

例如,当使用
-XPolyKinds
时,编译以下代码:

{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs, 
             FlexibleContexts #-}

module Foo where

data Foo :: (* -> *) where
  Foo :: c m zp' -> Foo (c m zp)

f :: forall c m zp d . Foo (c m zp) -> d
f y@(Foo (x :: c m a)) = g x y

g :: c m a -> Foo (c m b) -> d
g = error ""
{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs, 
             FlexibleContexts, PolyKinds #-}

module Foo where

data Foo :: (* -> *) where
  Foo :: (c :: k -> * -> *) m zp' -> Foo (c m zp)

f :: forall (c :: k -> * -> *) m zp d . Foo (c m zp) -> d
f y@(Foo x) = g x y

g :: c m a -> Foo (c m b) -> d
g = error ""
对于
-XDataKinds
版本,我还需要
g
上的kind签名:

{-# LANGUAGE ScopedTypeVariables, KindSignatures, GADTs, 
             FlexibleContexts, DataKinds #-}

module Foo where

data Bar

data Foo :: (* -> *) where
  Foo :: (c :: Bar -> * -> *) m zp' -> Foo (c m zp)

f :: forall (c :: Bar -> * -> *) m zp d . Foo (c m zp) -> d
f y@(Foo x) = g x y

g :: forall (c :: Bar -> * -> *) m a b d . c m a -> Foo (c m b) -> d
g = error ""

我不知道为什么我需要更多的SIG用于
数据类型
,而且必须到处复制它们有点烦人,但它确实完成了工作。

在您为
x
y
提供的类型签名中,
zp
zp'
是完全不相关的类型。您在函数的类型签名中提到了
zp
,但在其他地方没有提到
zp'
。你怎么能指望编译器推断出它们之间的关系?@user2407038我不知道。我只希望
c
m
是相同的。
g
的存根在
f
中无法使用提供的类型。它在
f
中与
g::astfdom(cma)->astfdom(cmb)->astfdom(cmb)
一起工作。
g
的类型可疑地与
f
的类型相似;它不能让我相信有任何有趣的函数需要这个证明。我问了一个关于类型相等的问题,它意味着种类相等。不,
x
的类型不是编写我给出的玩具代码所必需的,但它是编写我真正想要的代码所必需的。我为一个函数
g
添加了存根,希望能解决您的问题。“这正是它声称无法推断的…”不完全是。如果更改
discard
以返回
x
的代理,则它是相同的。您的代码将
y
的类型与自身匹配。我正在尝试匹配
x
y
中的类型。