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 Idris中元组的智能构造函数_Haskell_Idris - Fatal编程技术网

Haskell 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

我开始阅读第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
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
,因此是多余的。不幸的是,在做了这些更改之后,我无法编译代码:-/@MatthiasBerndt
a
确实是多余的
TupleVectType'
需要显式,以便
helper
可以访问它。使用
m-n
应该是
减去mn
,这样你就不必处理
LTE
证明,但你仍然需要处理其他证明和一些
重写
s,这样带
k
的变体就更容易键入(在键盘和键入系统意义上:-),尽管这不是严格必要的。