Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.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_Type Families - Fatal编程技术网

Haskell类型族和伪参数

Haskell类型族和伪参数,haskell,type-families,Haskell,Type Families,我制作了一个类似于numpy的数组的函数。它将列表转换为数组,将列表列表转换为二维数组,等等 它的工作原理如下: ghci> arrFromNestedLists ["hello", "world"] :: Array (Int, (Int, ())) Char array ((0,(0,())),(1,(4,()))) [((0,(0,())),'h'),((0,(1,())),'e'),((0,(2,())),'l'),((0,(3,())),'l'),((0,(4,())),'o')

我制作了一个类似于numpy的
数组的函数。它将列表转换为数组,将列表列表转换为二维数组,等等

它的工作原理如下:

ghci> arrFromNestedLists ["hello", "world"] :: Array (Int, (Int, ())) Char
array ((0,(0,())),(1,(4,()))) [((0,(0,())),'h'),((0,(1,())),'e'),((0,(2,())),'l'),((0,(3,())),'l'),((0,(4,())),'o'),((1,(0,())),'w'),((1,(1,())),'o'),((1,(2,())),'r'),((1,(3,())),'l'),((1,(4,())),'d')]
(Int,(Int,())
而不是
(Int,Int)
,因为我不知道用编程的方法来增加元组的长度。(旁白:有这样的方式吗?)

它的编码很笨拙,我必须做一个“变通方法”(将伪参数传递给函数),它才能工作。我不知道有没有更好的办法

下面是代码,被丑陋的解决方法的细节打断了:

{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, TypeFamilies #-}

type family ListOfIndex i a
type instance ListOfIndex () a = a
type instance ListOfIndex (Int, i) a = [ListOfIndex i a]

class Ix i => ArrConv i where
  acBounds :: a -> ListOfIndex i a -> (i, i)
  acFlatten :: i -> ListOfIndex i a -> [a]
acBounds
“应该”是
::列表索引i a->(i,i)
。对于
acFlatten
,也是如此。每个变量都有一个伪变量(
undefined
始终是给定的值),因为否则我无法将其编译:(

上面是在工作时传递的伪
undefined
参数。它告诉GHC使用
ListOfIndex
的哪个实例

instance ArrConv () where
  acBounds _ = const ((), ())
  acFlatten _ = (: [])
下面的函数应该是
ArrConv
实例中的
acBounds
函数,并在外部声明,因为我需要使用
ScopedTypeVariables
,我不知道如何在实例定义中的函数中执行此操作

acSucBounds
  :: forall a i. ArrConv i
  => a -> [ListOfIndex i a] -> ((Int, i), (Int, i))
acSucBounds _ lst =
  ((0, inStart), (length lst - 1, inEnd))
  where
    (inStart, inEnd) = acBounds (undefined :: a) (head lst)

instance ArrConv i => ArrConv (Int, i) where
  acBounds = acSucBounds
  acFlatten _ = concatMap (acFlatten (undefined :: i))

acBounds和acFlatten的额外参数是必需的,原因是不能从
ListOfIndex i a->(i,i)
ListOfIndex i a->[a]恢复类型
a
i
分别。一种解决方法是将这两种方法组合成
ListOfIndex i a->((i,i),a)
类型的方法
acArgs
。现在唯一的问题是在
(Int,i)
实例中使用它,以防止typechecker过度泛化其类型导致与以前相同的问题(例如,我们不能简单地使用
fst.acArgs

{-#语言类型族,FlexibleInstances} 导入数据。数组 索引i a的类型族列表 类型实例ListOfIndex()a=a 类型实例ListOfIndex(Int,i)a=[ListOfIndex i a] 第九类i=>ArrConv i,其中 acArgs::ListOfIndex i a->((i,i),[a]) 实例ArrConv(),其中 acArgs x=(((),()),[x]) 实例ArrConv i=>ArrConv(Int,i)其中 阿加尔湖= ((0,inStart),(长度lst-1,inEnd)),args>>=snd) 哪里 args=地图acArgs lst (inStart,inEnd)=fst(头部参数) arrFromNestedLists::ArrConv i=>ListOfIndex i a->Array i a arrFromNestedLists=uncurry listArray.acArgs
如果希望将
acBounds
acflatte
分开,可以向其中添加a,即
acBounds
将具有类型
acBounds::Proxy a->ListOfIndex i a->(i,i)
。这样就不需要
未定义的
参数,因为您可以只传递
(Proxy::SomeConcreteType)
到它;
acBounds
无法从中提取任何有用的值级别信息,因为它与单位类型同构(以非类型化的方式)。

“我不知道有什么编程方法可以增加元组的长度。”我认为你做不到。这是一个函数类型取决于值的完美例子。用依赖类型的语言(如
Agda
)很容易做到,但在Haskell中是不可能的。也许你可以用
GADTs
以某种方式给你一些依赖行为,但我不知道怎么做。可能是模板Haskell可能很有用:@primodemus:TH我可以为多达10维的数组创建
ArrConv
实例,它们将使用普通元组作为索引,这是一种改进。但我觉得限制是任意的,代码的可读性可能会低得多。看看您的原始示例,TH是如何实现的编译器应该知道您是想要
Array(Int,(Int,())Char
还是
Array(Int,())String
?我怀疑您的问题固有的模糊性导致需要传递伪参数来修复类型。@Reid Barton:太棒了!谢谢:)我对您的答案进行了一些重构(希望您不介意):它不再将
acArgs
传递给函数使其成为单态,而是现在只在一个位置使用它。
acSucBounds
  :: forall a i. ArrConv i
  => a -> [ListOfIndex i a] -> ((Int, i), (Int, i))
acSucBounds _ lst =
  ((0, inStart), (length lst - 1, inEnd))
  where
    (inStart, inEnd) = acBounds (undefined :: a) (head lst)

instance ArrConv i => ArrConv (Int, i) where
  acBounds = acSucBounds
  acFlatten _ = concatMap (acFlatten (undefined :: i))
{-# LANGUAGE TypeFamilies, FlexibleInstances #-} import Data.Array type family ListOfIndex i a type instance ListOfIndex () a = a type instance ListOfIndex (Int, i) a = [ListOfIndex i a] class Ix i => ArrConv i where acArgs :: ListOfIndex i a -> ((i, i), [a]) instance ArrConv () where acArgs x = (((), ()), [x]) instance ArrConv i => ArrConv (Int, i) where acArgs lst = (((0, inStart), (length lst - 1, inEnd)), args >>= snd) where args = map acArgs lst (inStart, inEnd) = fst (head args) arrFromNestedLists :: ArrConv i => ListOfIndex i a -> Array i a arrFromNestedLists = uncurry listArray . acArgs