Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.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 Level Computation - Fatal编程技术网

Haskell 使用静态大小列表减少堆栈溢出

Haskell 使用静态大小列表减少堆栈溢出,haskell,type-level-computation,Haskell,Type Level Computation,我有以下代码实现了静态大小的向量,实现为列表,可以很好地编译: {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeFamilies #-} {-# LA

我有以下代码实现了静态大小的向量,实现为列表,可以很好地编译:

{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE IncoherentInstances #-}

import GHC.TypeLits

infixr 5 :.
data Vector :: Nat -> * -> * where
  (:-:):: Vector 0 a
  (:.) :: a -> Vector (n-1) a -> Vector n a

deriving instance Show a => Show (Vector n a)

instance Functor (Vector n) where
  fmap f (:-:) = (:-:)
  fmap f (x :. xs) = f x :. fmap f xs

type x > y = CmpNat x y ~ 'GT

instance Applicative (Vector 0) where
  pure f    = (:-:)
  (<*>) _ _ = (:-:)

instance (Applicative (Vector (n-1)), n > 0 ) => Applicative (Vector n) where
  pure (f::a)          = f :. (pure f :: Vector (n-1) a)
  (f:.fs) <*> (x:.xs) = f x :. (fs <*> xs)
{-#选项_GHC-fplugin GHC.TypeLits.Normalise}
{-#语言不可判定实例}
{-#语言灵活语境#-}
{-#语言数据类型}
{-#语言类型运算符{-}
{-#语言类型族{-}
{-#语言GADTs}
{-#语言签名{-}
{-#语言独立派生}
{-#语言约束种类}
{-#语言范围类型变量#-}
{-#语言灵活实例}
{-#语言不连贯}
导入GHC.TypeLits
infixr 5:。
数据向量::Nat->*->*其中
(:-:)::向量0 a
(:::a->向量(n-1)a->向量n a
派生实例Show a=>Show(向量n a)
实例函子(向量n),其中
fmap f(:-:)=(:-:)
fmap f(x:.xs)=fx:。fmap f xs
类型x>y=CmpNat x y~'GT
实例应用程序(向量0),其中
纯f=(:-:)
() _ _ = (:-:)
实例(Applicative(Vector(n-1)),n>0)=>Applicative(Vector n),其中
纯(f::a)=f:。(纯f::向量(n-1)a)
(f:.fs)(x:.xs)=fx:。(财政司司长)
但是,当我尝试为这些向量定义元素和时,如下所示:

(<+>) :: Num a => Vector n a -> Vector n a -> Vector n a
v1 <+> v2 = (+) <$> v1 <*> v2
()::Num a=>向量NA->向量NA->向量NA
v1 v2=(+)v1 v2
我发现编译错误

Reduction stack overflow; size = 201
When simplifying the following type: Applicative (Vector s0)
(...)
In the expression: (+) <$> v1 <*> v2
减少堆栈溢出;尺寸=201
简化以下类型时:应用型(矢量s0)
(...)
在表达式中:(+)v1 v2
如果我可以在ghci中键入右手表达式,并且它工作正常,那么这个错误的原因是什么?将来如何避免它

我正在使用ghc 8.0.1和natnormalize 0.5.2

猜测:您不需要在
()
的签名中也添加[constraints]吗

[您的]
应用性
约束建议有效。您能否解释一下为什么我需要指定
(Vector n)
是Applicative的实例,因为所有向量长度都应该实例化为Applicative

简而言之,GHC无法归纳得出这一结论。相反,类型检查器在被告知您需要
Applicative(Vector n)
时所做的是后退并查看
Applicative(Vector(n-1))
,以查看是否满足
(Applicative(Vector(n-1)),n>0=>Applicative n
。由于您没有使用具体的
n
,因此它永远不会终止(这是与使用特定值的测试的差异)。既然如此,你需要提供额外的信息。顺便说一句,如果您尝试一些更平淡无奇的方法,您将得到相同的“减少堆栈溢出”错误,例如:

GHCi> :t undefined == (undefined :: [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[a]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]])
由于
Eq[a]
需要
Eq a
,如果
a~[b]
则还必须检查
Eq b
,以此类推


另一方面,据我所知,更常见的做法是根据
KnownNat
编写此类约束,而不是例如
Applicative
,以尽量减少必须在函数签名中传播的约束数量。例如(比我更精通这种类型级别编程的人可能会给出更具体的建议)。

(1)“我可以在ghci中键入右手表达式,而且效果很好”——如果你问它右手表达式的类型,ghci会怎么说?(2) 猜测:你不需要把
(Applicative(Vector(n-1)),n>0)
约束也放在
()
的签名中吗?下次我应该更具体一些,因为该表达式使用的是指定的值,而不是函数定义。然而,您关于应用约束的建议起了作用。您能详细解释一下为什么我需要指定(Vector n)是Applicative的实例,因为所有的向量长度都应该被实例化为Applicative吗?不需要(n>0)约束。