为什么不能解决`n`和`plus n 0`之间的约束?
Why can't the constraint between `n` and `plus n 0` be solved?
我正在尝试在 REPL 上重新加载包含以下 Idris 2 函数的源文件:
||| Apply a function across all elements of a vector.
||| @function The function to apply.
||| @input_vector The vector whose elements will be given as an argument to the function.
my_vect_map : (function : a -> b) -> (input_vector : Vect n a) -> Vect n b
my_vect_map function Nil = Nil
my_vect_map function (head :: tail) =
(my_vect_map' ((function head) :: Nil) tail) where
my_vect_map' : (accumulator : Vect length_b b) -> Vect length_a a -> Vect (length_b + length_a) b
my_vect_map' accumulator Nil = accumulator
my_vect_map' accumulator (head' :: tail') =
my_vect_map' (accumulator ++ ((function head') :: Nil)) tail'
但是它无法进行类型检查并出现错误:
Error: While processing right hand side of my_vect_map. While processing right hand side
of my_vect_map,my_vect_map'. Can't solve constraint
between: length_b (implicitly bound at page_75_section_3_2_exercises_solutions.idr:89:5--89:47) and plus length_b 0.
page_75_section_3_2_exercises_solutions.idr:89:36--89:47
|
89 | my_vect_map' accumulator Nil = accumulator
| ^^^^^^^^^^^
Error(s) building file page_75_section_3_2_exercises_solutions.idr
为什么类型检查器无法解决 length_b
和 plus length_b 0
之间的约束?我做错了什么,我该如何纠正?我尝试手动完成一些示例,似乎可行:
my_vect_map id [] => Nil => []
my_vect_map id ['a'] => my_vect_map id ('a' :: Nil) => my_vect_map' ((id 'a') :: Nil) Nil => my_vect_map' ('a' :: Nil) Nil => ('a' :: Nil) => ['a']
^length_b=1 ^length_a=0 ^length=1=length_b+length_a
my_vect_map id ['a', 'b'] => my_vect_map id ('a' :: ('b' :: Nil)) => my_vect_map' ((id 'a') :: Nil) ('b' :: Nil) => my_vect_map' ('a' :: Nil) ('b' :: Nil) => my_vect_map' (('a' :: Nil) ++ ((id 'b') :: Nil)) Nil => my_vect_map' (('a' :: Nil) ++ ('b' :: Nil)) Nil => my_vect_map' ('a' :: ('b' :: Nil)) Nil => ('a' :: ('b' :: Nil)) => ['a', 'b']
^length_b=1 ^length_a=1 ^length_b=2 ^length_a=0 ^length=2=length_b+length_a
此外,我如何让类型检查器意识到 length_b + length_a
等于 n
(因为我认为我没有设法将这种关系编码到函数中)?
你可以用Data.Nat
中的rewrite rule plusZeroRightNeutral
来证明n + 0 = n
。
不过您可能需要重新考虑一下这个函数。
您可以非常简单地创建矢量图:
my_vect_map : (a -> b) -> Vect n a -> Vect n b
my_vect_map fn [] = []
my_vect_map fn (x :: xs) = fn x :: my_vect_map fn xs
编辑
这是 map
的尾递归版本:
mutual
rhs : {m : Nat} -> (a -> b) -> a -> Vect m b -> Vect len a -> Vect (plus m (S len)) b
rhs f x acc xs = rewrite sym $ plusSuccRightSucc m len in my_vect_map' f (f x :: acc) xs
my_vect_map' : {m : Nat} -> (a -> b) -> Vect m b -> Vect n a -> Vect (m + n) b
my_vect_map' f acc [] = rewrite plusZeroRightNeutral m in acc
my_vect_map' f acc (x :: xs) = rhs f x acc xs
my_vect_map : (a -> b) -> Vect n a -> Vect n b
my_vect_map f = reverse . my_vect_map' f []
rhs
的唯一目的是暴露len
,xs
的大小。
我们还使用 {}
将类型变量引入值级别的范围。
希望对您有所帮助。
我正在尝试在 REPL 上重新加载包含以下 Idris 2 函数的源文件:
||| Apply a function across all elements of a vector.
||| @function The function to apply.
||| @input_vector The vector whose elements will be given as an argument to the function.
my_vect_map : (function : a -> b) -> (input_vector : Vect n a) -> Vect n b
my_vect_map function Nil = Nil
my_vect_map function (head :: tail) =
(my_vect_map' ((function head) :: Nil) tail) where
my_vect_map' : (accumulator : Vect length_b b) -> Vect length_a a -> Vect (length_b + length_a) b
my_vect_map' accumulator Nil = accumulator
my_vect_map' accumulator (head' :: tail') =
my_vect_map' (accumulator ++ ((function head') :: Nil)) tail'
但是它无法进行类型检查并出现错误:
Error: While processing right hand side of my_vect_map. While processing right hand side
of my_vect_map,my_vect_map'. Can't solve constraint
between: length_b (implicitly bound at page_75_section_3_2_exercises_solutions.idr:89:5--89:47) and plus length_b 0.
page_75_section_3_2_exercises_solutions.idr:89:36--89:47
|
89 | my_vect_map' accumulator Nil = accumulator
| ^^^^^^^^^^^
Error(s) building file page_75_section_3_2_exercises_solutions.idr
为什么类型检查器无法解决 length_b
和 plus length_b 0
之间的约束?我做错了什么,我该如何纠正?我尝试手动完成一些示例,似乎可行:
my_vect_map id [] => Nil => []
my_vect_map id ['a'] => my_vect_map id ('a' :: Nil) => my_vect_map' ((id 'a') :: Nil) Nil => my_vect_map' ('a' :: Nil) Nil => ('a' :: Nil) => ['a']
^length_b=1 ^length_a=0 ^length=1=length_b+length_a
my_vect_map id ['a', 'b'] => my_vect_map id ('a' :: ('b' :: Nil)) => my_vect_map' ((id 'a') :: Nil) ('b' :: Nil) => my_vect_map' ('a' :: Nil) ('b' :: Nil) => my_vect_map' (('a' :: Nil) ++ ((id 'b') :: Nil)) Nil => my_vect_map' (('a' :: Nil) ++ ('b' :: Nil)) Nil => my_vect_map' ('a' :: ('b' :: Nil)) Nil => ('a' :: ('b' :: Nil)) => ['a', 'b']
^length_b=1 ^length_a=1 ^length_b=2 ^length_a=0 ^length=2=length_b+length_a
此外,我如何让类型检查器意识到 length_b + length_a
等于 n
(因为我认为我没有设法将这种关系编码到函数中)?
你可以用Data.Nat
中的rewrite rule plusZeroRightNeutral
来证明n + 0 = n
。
不过您可能需要重新考虑一下这个函数。
您可以非常简单地创建矢量图:
my_vect_map : (a -> b) -> Vect n a -> Vect n b
my_vect_map fn [] = []
my_vect_map fn (x :: xs) = fn x :: my_vect_map fn xs
编辑
这是 map
的尾递归版本:
mutual
rhs : {m : Nat} -> (a -> b) -> a -> Vect m b -> Vect len a -> Vect (plus m (S len)) b
rhs f x acc xs = rewrite sym $ plusSuccRightSucc m len in my_vect_map' f (f x :: acc) xs
my_vect_map' : {m : Nat} -> (a -> b) -> Vect m b -> Vect n a -> Vect (m + n) b
my_vect_map' f acc [] = rewrite plusZeroRightNeutral m in acc
my_vect_map' f acc (x :: xs) = rhs f x acc xs
my_vect_map : (a -> b) -> Vect n a -> Vect n b
my_vect_map f = reverse . my_vect_map' f []
rhs
的唯一目的是暴露len
,xs
的大小。
我们还使用 {}
将类型变量引入值级别的范围。
希望对您有所帮助。