如何确定 HVect 的所有子维度?
How to determine all sub-dimensions of a HVect?
我想将 HVect
的所有子维度确定为 HVect
。
示例:
import Data.HVect
myHVect : HVect [Int, String, List Nat]
myHVect = [42, "text", [1, 2, 3]]
subDimensions : HVect [ HVect [Int], HVect [Int, String], HVect [Int, String, List Nat] ]
subDimensions = subDimHVect myHVect
-- [ [42], [42, "text"], [42, "text", [1, 2, 3]] ]
我的方法是这样的:
subDimHVect v = subDimHVect' [] [] v
where
subDimHVect' result _ [] = result
subDimHVect' result lastDim (x::xs) =
let nextDim = lastDim ++ [x] in
subDimHVect' (result ++ [nextDim]) nextDim xs
但我不知道如何正确输入 subDimHVect
和 subDimHVect'
。实施似乎没问题:
实例手动计算:
subDimHVect [42, "text", [1, 2, 3]]
= subDimHVect' [] [] [42, "text", [1, 2, 3]]
= subDimHVect' [[42]] [42] ["text", [1, 2, 3]]
= subDimHVect' [[42], [42, "text"]] [42, "text"] [[1, 2, 3]]
= subDimHVect' [[42], [42, "text"], [42, "text", [1, 2, 3]]] [42, "text", [1, 2, 3]] []
= [[42], [42, "text"], [42, "text", [1, 2, 3]]]
我对 Idris 和依赖类型还很陌生。如果能帮我找到丢失的类型签名,我将不胜感激。
编辑:
我发现了另一种可能更容易输入的方法,尽管我也无法弄清楚类型 ():
subDimHVect v = reverse (subDimHVect' (reverse v))
where
subDimHVect' [] = []
subDimHVect' (x::xs) = [(x::xs)] ++ (subDimHVect' xs)
示例的手动计算(使用第二种方法):
subDimHVect [42, "text", [1, 2, 3]]
= reverse (subDimHVect' (reverse [42, "text", [1, 2, 3]]))
= reverse (subDimHVect' [[1, 2, 3], "text", 42])
= reverse ([ [[1, 2, 3], "text", 42] ] ++ (subDimHVect' ["text", 42]))
= reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ (subDimHVect' [42]))
= reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ [ [42] ] ++ (subDimHVect' []))
= reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ [ [42] ] ++ [])
= reverse ([ [[1, 2, 3], "text", 42], ["text", 42], [42] ])
= [ [42], [42, "text"], [42, "text", [1, 2, 3]] ]
第一次尝试:
subDimensions : HVect ts -> HVect xs
xs
将被视为隐式参数(如在 subDimensions : {ts : Vect n Type} -> {xs : Vect k Type} -> HVect ts -> HVect xs
中),因此调用者可以说明结果 HVect
的样子。那是不对的。我们可以同时创建 xs
(如果您了解如何操作,请参阅此答案的历史记录):
subDimensions : HVect {k} ts -> (xs : (Vect k Type) ** HVect xs)
然而,一个
subDimensions : HVect ts -> HVect (dimType ts)
会更有用。在您第二次尝试之后,我们可以创建
dimType : Vect k Type -> Vect k Type
dimType [] = []
dimType (x :: xs) = (HVect (vreverse (x::xs))) :: dimType xs
并根据类型的结构,我们定义了助手 subDimensions'
:
subDimensions' : HVect ts -> HVect (dimType ts)
subDimensions' [] = []
subDimensions' (x :: xs) = (hreverse (x :: xs)) :: subDimensions' xs
和包装器
subDimensions : HVect ts -> HVect (vreverse (dimType (vreverse ts)))
subDimensions xs = hreverse $ subDimensions' $ hreverse xs
(hreverse
和 vreverse
的定义参见 )
我想将 HVect
的所有子维度确定为 HVect
。
示例:
import Data.HVect
myHVect : HVect [Int, String, List Nat]
myHVect = [42, "text", [1, 2, 3]]
subDimensions : HVect [ HVect [Int], HVect [Int, String], HVect [Int, String, List Nat] ]
subDimensions = subDimHVect myHVect
-- [ [42], [42, "text"], [42, "text", [1, 2, 3]] ]
我的方法是这样的:
subDimHVect v = subDimHVect' [] [] v
where
subDimHVect' result _ [] = result
subDimHVect' result lastDim (x::xs) =
let nextDim = lastDim ++ [x] in
subDimHVect' (result ++ [nextDim]) nextDim xs
但我不知道如何正确输入 subDimHVect
和 subDimHVect'
。实施似乎没问题:
实例手动计算:
subDimHVect [42, "text", [1, 2, 3]]
= subDimHVect' [] [] [42, "text", [1, 2, 3]]
= subDimHVect' [[42]] [42] ["text", [1, 2, 3]]
= subDimHVect' [[42], [42, "text"]] [42, "text"] [[1, 2, 3]]
= subDimHVect' [[42], [42, "text"], [42, "text", [1, 2, 3]]] [42, "text", [1, 2, 3]] []
= [[42], [42, "text"], [42, "text", [1, 2, 3]]]
我对 Idris 和依赖类型还很陌生。如果能帮我找到丢失的类型签名,我将不胜感激。
编辑:
我发现了另一种可能更容易输入的方法,尽管我也无法弄清楚类型 (
subDimHVect v = reverse (subDimHVect' (reverse v))
where
subDimHVect' [] = []
subDimHVect' (x::xs) = [(x::xs)] ++ (subDimHVect' xs)
示例的手动计算(使用第二种方法):
subDimHVect [42, "text", [1, 2, 3]]
= reverse (subDimHVect' (reverse [42, "text", [1, 2, 3]]))
= reverse (subDimHVect' [[1, 2, 3], "text", 42])
= reverse ([ [[1, 2, 3], "text", 42] ] ++ (subDimHVect' ["text", 42]))
= reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ (subDimHVect' [42]))
= reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ [ [42] ] ++ (subDimHVect' []))
= reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ [ [42] ] ++ [])
= reverse ([ [[1, 2, 3], "text", 42], ["text", 42], [42] ])
= [ [42], [42, "text"], [42, "text", [1, 2, 3]] ]
第一次尝试:
subDimensions : HVect ts -> HVect xs
xs
将被视为隐式参数(如在 subDimensions : {ts : Vect n Type} -> {xs : Vect k Type} -> HVect ts -> HVect xs
中),因此调用者可以说明结果 HVect
的样子。那是不对的。我们可以同时创建 xs
(如果您了解如何操作,请参阅此答案的历史记录):
subDimensions : HVect {k} ts -> (xs : (Vect k Type) ** HVect xs)
然而,一个
subDimensions : HVect ts -> HVect (dimType ts)
会更有用。在您第二次尝试之后,我们可以创建
dimType : Vect k Type -> Vect k Type
dimType [] = []
dimType (x :: xs) = (HVect (vreverse (x::xs))) :: dimType xs
并根据类型的结构,我们定义了助手 subDimensions'
:
subDimensions' : HVect ts -> HVect (dimType ts)
subDimensions' [] = []
subDimensions' (x :: xs) = (hreverse (x :: xs)) :: subDimensions' xs
和包装器
subDimensions : HVect ts -> HVect (vreverse (dimType (vreverse ts)))
subDimensions xs = hreverse $ subDimensions' $ hreverse xs
(hreverse
和 vreverse
的定义参见