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 RankNTypes:将相同的函数应用于不同类型的对_Haskell_Ghc_Higher Rank Types - Fatal编程技术网

Haskell RankNTypes:将相同的函数应用于不同类型的对

Haskell RankNTypes:将相同的函数应用于不同类型的对,haskell,ghc,higher-rank-types,Haskell,Ghc,Higher Rank Types,我试图定义此函数以重新组合三个成对列表: {-# LANGUAGE RankNTypes #-} mapAndZip3 :: (forall x. x -> f x) -> [a] -> [b] -> [c] -> [(f a, f b, f c)] mapAndZip3 f la lb lc = zipWith3 (\a b c -> (f a, f b, f c)) la lb lc

我试图定义此函数以重新组合三个成对列表:

{-# LANGUAGE RankNTypes #-}

mapAndZip3 :: (forall x. x -> f x) -> [a] -> [b] -> [c] 
                                   -> [(f a, f b, f c)]
mapAndZip3 f la lb lc = zipWith3 (\a b c -> (f a, f b, f c)) la lb lc


main = do
    let x = mapAndZip3 (fst) [(1,"fruit"), (2,"martini")] 
                             [("chips","fish"),("rice","steak")]
                             [(5,"cake"),(4,"pudding")]
    print x -- was expecting [(1,"chips",5), (2,"rice",4)]
起初我没有包括
RankNTypes
forall
,但在seing之后,即
liftTup
定义,我认为这应该足够了

但很明显,事实并非如此,因为我仍然犯了一个错误:

mapAndZip3.hs:8:25:
Couldn't match type `x' with `(f0 x, b0)'
  `x' is a rigid type variable bound by
      a type expected by the context: x -> f0 x at mapAndZip3.hs:8:13
Expected type: x -> f0 x
  Actual type: (f0 x, b0) -> f0 x
In the first argument of `mapAndZip3', namely `(fst)'
显然,我对所有关键字的
理解有限,但从我的理解来看,在这种情况下,应该允许
f
接受任何类型。我不明白的是:一旦在给定的上下文中使用一次,该定义是否会在剩余的上下文中得到“修复”

看起来不是这样,因为如果我用int替换“chips”和“rice”,编译器仍然会抱怨,所以我猜我是在假设出了什么错误(当然,如果我删除
mapAndZip3
的类型注释,在后一种情况下,一切都会解决,因为签名被简化为
mapAndZip3::(a->t)->[a]->[a]->[a]->[(t,t,t)]
,但这不是我想要的)


我也发现了这一点,但无法确定这是否是同一个问题,因为我尝试应用的函数不是
id
,而是
fst
snd
,实际上返回不同类型的函数
(a->b)
签名中的问题是
f
。让我们稍微扩展一下:

mapAndZip3 :: forall (a :: *) (b :: *) (c :: *) (f :: *->*)
           =>  (forall x. x -> f x) -> [a] -> [b] -> [c] 
                               -> [(f a, f b, f c)]
f
在这里应该是“任何类型级别的函数”,在您的实例化中,它应该是
类型f(a,b)=a
。但是Haskell不允许抽象类型级别的函数,只允许抽象类型构造函数,比如
可能
IO
。因此,
mapAndZip3仅仅
实际上是可能的,但是
fst
不构造而是解构元组类型

类型级别的函数在Haskell 98中甚至不存在,它们只在以后才可能存在。问题基本上是Haskell的kind语言不是类型1,但类型级函数必须是总函数2。但是,您不能真正定义任何在所有类型上定义的非平凡函数(即除了
id
或类型构造函数之外的函数)。类型级别
fst
当然不是total,它只适用于元组类型

因此,要使用这些函数,您需要明确地以其他方式指定它们的上下文。使用
TypeFamilies
时,其工作原理如下:

class TypeFunctionDomain d where
  type TypeFunction d :: *

instance TypeFunctionDomain (a,b) where
  type TypeFunction (a,b) = a

mapAndZip3 :: (forall x. TypeFunctionDomain x => x -> TypeFunction x)
          -> [a] -> [b] -> [c] 
                   -> [(TypeFunction a, TypeFunction b, TypeFunction c)]
然而,这并不是您真正想要的:不可能在同一范围内定义与
snd
相对应的
TypeFunctionDomain
实例,这意味着mapAndZip3实际上根本不是多态的,而只能与单个函数一起工作

这些问题只能在依赖类型的语言中正确解决,例如,类型实际上只是类型的类型,您可以定义类型级函数以及值级函数。但这是有代价的:所有函数都必须是总函数!这并不是一件坏事,但这意味着这些语言通常不是真正的图灵完整的(这需要无限循环/递归的可能性;然而
关于完整结果评估)


1.随着经济的发展,情况发生了一些变化


2不同于C++,它允许-尽管有非常可怕的语法-鸭型的类型级函数,通过模板。这可能是一个很好的特性,但其后果之一是您经常会收到完全无法读取的错误消息(与实际问题的关系甚至比GHC最糟糕的“可能修复”提示还要小……)尝试使用隐式域之外的类型参数实例化模板时。

问题在于
fst
没有所需的类型

(forall x. x -> f x)
fst
的类型为

fst :: (a, b) -> a
a
不是
f(a,b)
的形式。
f
有一个必须用类型构造函数实例化的变量,类似于
[]
可能
或者Bool
f
不能代表任何像
a(a,b)->a这样的“类型函数”,它必须是一个类型构造函数

如果我们为其提供所需类型的函数(抱歉,愚蠢的示例):


因为这里的
fst0
的类型是
a->((,)Bool)a
,它的形式是
x->fx
,谢谢!我真的很难选择“一个”正确答案,因为两者都解释了这是不可能的。虽然我非常喜欢丹尼尔·菲舍尔的答案,因为一开始它是最容易理解的,但左撇子的答案确实给了我一些额外的上下文。为双方干杯!
{-# LANGUAGE RankNTypes #-}

mapAndZip3 :: (forall x. x -> f x) -> [a] -> [b] -> [c]
                                   -> [(f a, f b, f c)]
mapAndZip3 f la lb lc = zipWith3 (\a b c -> (f a, f b, f c)) la lb lc

fst0 x = (True,x)

main = do
    let x = mapAndZip3 (fst0) [(1 :: Int,"fruit"), (2,"martini")]
                             [("chips","fish"),("rice","steak")]
                             [(5 :: Int,"cake"),(4,"pudding")]
    print x