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 具有反射和数据类型的类型推断_Haskell_Reflection_Type Inference_Data Kinds - Fatal编程技术网

Haskell 具有反射和数据类型的类型推断

Haskell 具有反射和数据类型的类型推断,haskell,reflection,type-inference,data-kinds,Haskell,Reflection,Type Inference,Data Kinds,我很难让GHC在一个应该很明显的地方推断出一种类型。下面是演示该问题的完整片段 {-# LANGUAGE DataKinds, ScopedTypeVariables, KindSignatures, TypeOperators, GADTs #-} import Data.Reflection import Data.Proxy import Data.Tagged -- heterogeneous list, wrapping kind [*] as * data HList :: [*

我很难让GHC在一个应该很明显的地方推断出一种类型。下面是演示该问题的完整片段

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

import Data.Reflection
import Data.Proxy
import Data.Tagged

-- heterogeneous list, wrapping kind [*] as *
data HList :: [*] -> * where
              HNil :: HList '[]
              HCons :: a -> HList as -> HList (a ': as)

main = test2

test1 = do
    let x = HCons 3 HNil :: HList '[Int]
        c = case x of (HCons w HNil) -> w
    print c

test2 = reify True (\(_::Proxy a) -> do

    let x = HCons (Tagged 3) HNil :: HList '[Tagged a Int]
        c = case x of (HCons w HNil) -> w
    print $ untag (c :: Tagged a Int))
test1
中,我可以打印
c
,而无需给出
c
和显式类型,正如我所期望的那样。
c
的类型由
x
上的显式签名推断:即
HList
中的第一个元素的类型为
Int

但是,在
test2
中,需要在
c
上显式签名。如果我只是在
test2
中打印$untag c,我得到

Test.hs:22:32:
    Couldn't match type `s0' with `s'
      `s0' is untouchable
           inside the constraints (as ~ '[] *)
           bound at a pattern with constructor
                      HNil :: HList ('[] *),
                    in a case alternative
      `s' is a rigid type variable bound by
          a type expected by the context:
            Reifies * s Bool => Proxy * s -> IO ()
          at Test.hs:19:9
    Expected type: Tagged * s0 Int
      Actual type: a
    In the pattern: HNil
    In the pattern: HCons w HNil
    In a case alternative: (HCons w HNil) -> w

为什么GHC不能从
test1
中给
x
的显式类型推断
c
的类型?

我发现这些错误与let绑定有关。。。虽然我不知道确切的原因或者它是否真的是GHC中的bug。解决方法是使用case语句:

test4 = reify True $ \ (_::Proxy a) -> do
  let x = HCons (Tagged 4) HNil :: HList '[Tagged a Int]
      c = case x of (HCons w HNil) -> w
  print $ untag (c :: Tagged a Int)

test5 = reify True $ \ (_::Proxy a) -> do
  case HCons (Tagged 5) HNil :: HList '[Tagged a Int] of
    HCons w HNil -> print $ untag w

值得一提的是,老式的
data-HCons a b=HCons a b
data-HNil=HNil
没有这个问题。我发现这些错误与let绑定有关。。。虽然我不知道确切的原因或者它是否真的是GHC中的bug。解决方法是用一个案例陈述来代替:@NathanHowell:有趣,而且很烦人。@Eric:我同意。我理解为什么当GADT或存在量化将新类型变量引入范围时会发生这种情况。。。但这并没有起作用,而且似乎应该起作用。希望有人能插嘴。@NathanHowell:这篇文章似乎没有引起太多关注。如果你写下你的评论并在回答中包含代码,我会接受。