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)约束。