Haskell Idris中元组的智能构造函数
我开始阅读第6章“使用Idris进行类型驱动开发”,并尝试为元组向量编写智能构造函数Haskell Idris中元组的智能构造函数,haskell,idris,Haskell,Idris,我开始阅读第6章“使用Idris进行类型驱动开发”,并尝试为元组向量编写智能构造函数 TupleVect : Nat -> Type -> Type TupleVect Z _ = () TupleVect (S k) a = (a, TupleVect k a) someValue : TupleVect 4 Nat someValue = (1,2,3,4,()) TupleVectConstructorType : Nat -> Type -> Type Tup
TupleVect : Nat -> Type -> Type
TupleVect Z _ = ()
TupleVect (S k) a = (a, TupleVect k a)
someValue : TupleVect 4 Nat
someValue = (1,2,3,4,())
TupleVectConstructorType : Nat -> Type -> Type
TupleVectConstructorType n typ = helper n
where
helper : Nat -> Type
helper Z = TupleVect n typ
helper (S k) = typ -> helper k
tupleVect : (n : Nat) -> (a : Type) -> TupleVectConstructorType n a
tupleVect Z a = ()
tupleVect (S Z) a = \val => (val, ())
tupleVect (S (S Z)) a = \val2 => \val1 => (val2, val1, ())
-- ??? how to create tupleVect (S k) a
如何为任意k创建构造函数?我对Idris几乎一无所知,只知道它是一种依赖类型、类似Haskell的语言。但我觉得这个问题很有趣,所以我试了一下 显然,这里需要一个递归解决方案。我的想法是使用一个额外的参数
f
,它累加函数到目前为止已经消耗的val1
。val\n
参数。当到达基本情况时,返回f
tupleVectHelper Z a f = f
tupleVectHelper (S n) a f = \val => tupleVectHelper n a (val, f)
tupleVect n a = tupleVectHelper n a ()
我不知道这是否有效,我还没有弄清楚如何编写tuplelectHelper
的类型,但我已经尝试过手动替换n=3
,虽然生成的元组是反向的,但它似乎在纸上是可行的。但我认为这不太难解决
希望这有帮助 基本上是@Matthias Berndt的想法。倒计时要添加的箭头,同时使最后的元组变长。为此,我们需要从
tuplelectType
访问更宽容的助手
TupleVectType' : Nat -> Nat -> Type -> Type
TupleVectType' Z n a = TupleVect n a
TupleVectType' (S k) n a = a -> TupleVectType' k (S n) a
TupleVectType : Nat -> Type -> Type
TupleVectType n = TupleVectType' n Z
tupleVect : (n : Nat) -> (a : Type) -> TupleVectType n a
tupleVect n a = helper n Z a ()
where
helper : (k, n : Nat) -> (a : Type) -> (acc : TupleVect n a)
-> TupleVectType' k n a
helper Z n a acc = acc
helper (S k) n a acc = \x => helper k (S n) a (x, acc)
someValue2 : TupleVect 4 Nat
someValue2 = (tupleVect 4 Nat) 4 3 2 1
不过请注意,这将导致
\v2=>\v1=>(v1,v2,())
而不是\v2=>\v1=>(v2,v1,())
,因为前者更适合TupleVect(sk)a=(a,TupleVect k a)的递归定义。
很好的解决方案。但简化它应该是可能的helper
不需要a
type参数,因为您可以从封闭范围中使用a
。对于TupleVectType'
,您可以在tupleVect
的where
子句中声明它。然后在helper
中有k
。如果将tupleVect
中的n
变量重命名为m
,则k
只是m-n
,因此是多余的。不幸的是,在做了这些更改之后,我无法编译代码:-/@MatthiasBerndta
确实是多余的TupleVectType'
需要显式,以便helper
可以访问它。使用m-n
应该是减去mn
,这样你就不必处理LTE
证明,但你仍然需要处理其他证明和一些重写
s,这样带k
的变体就更容易键入(在键盘和键入系统意义上:-),尽管这不是严格必要的。