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_Types - Fatal编程技术网

Haskell 为什么可以';类型族上的模式匹配吗?

Haskell 为什么可以';类型族上的模式匹配吗?,haskell,types,Haskell,Types,考虑以下代码: {-# LANGUAGE TypeFamilies #-} data Twothings a b = Twothings a b type family Leftthing a where Leftthing (Twothings a b) = Leftthing a Leftthing a = a leftthing :: a -> Leftthing a leftthing (Twothings a b) = leftthing a leftthing b

考虑以下代码:

{-# LANGUAGE TypeFamilies #-}

data Twothings a b = Twothings a b

type family Leftthing a where
  Leftthing (Twothings a b) = Leftthing a
  Leftthing a = a

leftthing :: a -> Leftthing a
leftthing (Twothings a b) = leftthing a
leftthing b = b
它未编译,出现以下错误:

Couldn't match expected type ‘a’
                  with actual type ‘Twothings a0 t0’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          leftthing :: forall a. a -> Leftthing a
它抱怨行
leftthing(twoothingab)=leftthinga
。如果我理解正确,它无法将类型签名中的类型变量
a
与构造函数的类型
twoothings
统一起来。好吧,这似乎有道理。但是,我怎样才能在类型签名中定义具有类型族的函数呢

leftthing :: a -> Leftthing a
您的意思是,
leftthing
的调用者可以选择
a
是什么

当你写的时候

leftthing (Twothings a b) = leftthing a
您假定他们选择了
twoothings
类型,但情况并非如此,因此您的程序被拒绝

您可能认为您正在测试他们是否选择了
twoothings
类型,但没有!类型信息在运行时之前被擦除,因此无法进行此类测试

您可以尝试还原必要的运行时信息。首先,让我修复
Leftthing
Leftthing
之间的不一致性

type family Leftthing a where
  Leftthing (Twothings a b) = Leftthing{-you forgot the recursion!-} a
  Leftthing a = a
现在我们可以将证人的GADT定义为
twoothing
ness

data IsItTwothings :: * -> * where
  YesItIs   :: IsItTwothings a -> IsItTwothings (Twothings a b)
  NoItIsn't :: Leftthing a ~ a => IsItTwothings a
            -- ^^^^^^^^^^^^^^^ this constraint will hold for any type
            -- which is *definitely not* a Twothings type
然后我们可以传证人作为论点:

leftthing :: IsItTwothings a -> a -> Leftthing a
leftthing (YesItIs r) (Twothings a b) = leftthing r a
leftthing NoItIsn't   b               = b
实际上,见证是类型根处左嵌套的
twoothings
es的数量的一元编码。这些信息足以在运行时确定要执行的正确解包量

> leftthing (YesItIs (YesItIs NoItIsn't)) (Twothings (Twothings True 11) (Twothings "strange" [42]))
True
总之,您无法通过对值进行模式匹配来找到类型。相反,您需要知道进行模式匹配的类型(因为类型决定内存布局,并且没有运行时类型标记)。您不能直接在类型上进行模式匹配(因为它们只是不需要进行匹配)。您可以构造作为类型结构的运行时证据的数据类型,并在这些数据类型上进行匹配

也许有一天,如果你给它类型,你的程序会工作

leftthing :: pi a. a -> Leftthing a

其中,
pi
是相关量词,表示隐藏类型参数不会被删除,而是在运行时传递和匹配。那一天还没有到来,但我想它会到来。

你想解决的问题是什么?我可以举出使用类型族的例子,但我更愿意回答一个更具体的问题。感谢您发现我在类型族声明中的错误!(现已修复)