F# 在异构列表上,是否可以使压缩和解压与原始列表相同?
我正在讨论异构列表上下文中的zip操作。我正在开发一种轻度依赖类型的语言,将它们用作元组F# 在异构列表上,是否可以使压缩和解压与原始列表相同?,f#,F#,我正在讨论异构列表上下文中的zip操作。我正在开发一种轻度依赖类型的语言,将它们用作元组 type T = | S of string | R of T list let rec zip l = let is_all_r_empty x = List.forall (function R [] -> true | _ -> false) x let rec loop acc_total acc_head acc_tail x = match x wi
type T =
| S of string
| R of T list
let rec zip l =
let is_all_r_empty x = List.forall (function R [] -> true | _ -> false) x
let rec loop acc_total acc_head acc_tail x =
match x with
| S _ :: _ -> R l
| R [] :: ys ->
if List.isEmpty acc_head && is_all_r_empty ys then List.rev acc_total |> R
else R l
| R (x :: xs) :: ys -> loop acc_total (x :: acc_head) (R xs :: acc_tail) ys
| [] ->
match acc_tail with
| _ :: _ -> loop ((List.rev acc_head |> zip) :: acc_total) [] [] (List.rev acc_tail)
| _ -> List.rev acc_total |> R
loop [] [] [] l
let rec unzip l =
let transpose l =
let is_all_empty x = List.forall (function _ :: _ -> false | _ -> true) x
let rec loop acc_total acc_head acc_tail = function
| (x :: xs) :: ys -> loop acc_total (x :: acc_head) (xs :: acc_tail) ys
| [] :: ys ->
if List.isEmpty acc_head && is_all_empty ys then loop acc_total acc_head acc_tail ys
else l
| [] ->
match acc_tail with
| _ :: _ -> loop (List.rev acc_head :: acc_total) [] [] (List.rev acc_tail)
| _ -> List.rev acc_total
loop [] [] [] l
let is_all_r x = List.forall (function R _ -> true | _ -> false) x
match l with
| R x when is_all_r x -> List.map unzip x |> transpose |> List.map R
| R x -> x
| S _ -> failwith "Unzip called on S."
//let a = R [R [S "a"; S "t"]; R [S "b"; S "w"]; R [S "c"; S "e"]]
//let b = R [R [S "1"; S "4"]; R [S "5"; S "r"]; R [S "3"; S "6"]]
//let c = R [R [S "z"; S "v"]; R [S "x"; S "b"]; R [S "c"; S "2"]]
//
//let t3 = zip [a;b]
//let t4 = zip [t3;c]
//let u1 = unzip t4
//let r1 = u1 = [t3;c]
//let u2 = unzip t3
//let r2 = u2 = [a;b] // The above works fine on tuples with regular dimensions.
let a = R [R [S "q"; S "w"; S "e"]]
let b = R [R [S "a"; S "s"]; R [S "z"]; S "wqe"]
let ab = [a;b]
let t = zip ab
let t' = unzip t
ab = t' // This is false, but I would like the ziping and then unziping to be reversible if possible.
压缩和解压通常可以表示为一个维度移位或一系列转置。这就是这两个功能所做的一切
它们在规则元组上表现良好,但我希望zip+unzip在不规则元组上也是同构的。我的直觉告诉我,这对他们要求太多了
我需要第二个意见。#r./../packages/FsCheck.2.8.0/lib/net452/FsCheck.dll”
#r "../../packages/FsCheck.2.8.0/lib/net452/FsCheck.dll"
type T =
| S of string
| VV of T list
let transpose l on_fail on_succ =
let is_all_vv_empty x = List.forall (function VV [] -> true | _ -> false) x
let rec loop acc_total acc_head acc_tail = function
| VV [] :: ys ->
if List.isEmpty acc_head && is_all_vv_empty ys then
if List.isEmpty acc_total then failwith "Empty inputs in the inner dimension to transpose are invalid."
else List.rev acc_total |> on_succ
else on_fail ()
| VV (x :: xs) :: ys -> loop acc_total (x :: acc_head) (VV xs :: acc_tail) ys
| _ :: _ -> on_fail ()
| [] ->
match acc_tail with
| _ :: _ -> loop (VV (List.rev acc_head) :: acc_total) [] [] (List.rev acc_tail)
| _ -> List.rev acc_total |> on_succ
loop [] [] [] l
let rec zip l =
match l with
| _ :: _ -> transpose l (fun _ -> l) (List.map (function VV x -> zip x | x -> x)) |> VV
| _ -> failwith "Empty input to zip is invalid."
let rec unzip l =
let is_all_vv x = List.forall (function VV _ -> true | _ -> false) x
match l with
| VV x ->
match x with
| _ :: _ when is_all_vv x -> let t = List.map (unzip >> VV) x in transpose t (fun _ -> x) id
| _ :: _ -> x
| _ -> failwith "Empty inputs to unzip are invalid."
| S _ -> failwith "Unzip called on S."
open FsCheck
open System
let gen_t =
let mutable gen_t = None
let gen_s () = Gen.map S Arb.generate<string>
let gen_vv size = Gen.nonEmptyListOf (gen_t.Value size) |> Gen.map VV
gen_t <-
fun size ->
match size with
| 0 -> gen_s()
| _ when size > 0 -> Gen.oneof [gen_s (); gen_vv (size-1)]
| _ -> failwith "impossible"
|> Some
gen_t.Value
|> Gen.sized
let gen_t_list_irregular = Gen.nonEmptyListOf gen_t
let gen_t_list_regular = Gen.map2 List.replicate (Gen.choose(1,10)) gen_t
type MyGenerators =
static member Tuple() = Arb.fromGen gen_t
static member TupleList() = Arb.fromGen gen_t_list_regular
Arb.register<MyGenerators>()
let zip_and_unzip orig = zip orig |> unzip
let zip_and_unzip_eq_orig orig = zip_and_unzip orig = orig
// For regular tuples it passes with flying colors.
Check.One ({Config.Quick with EndSize = 10}, zip_and_unzip_eq_orig)
// I can't get it to be isomorphic for irregularly sized arrays as expected.
//let f x =
// let x' = zip x
// printfn "x'=%A" x'
// printfn "unzip x'=%A" (unzip x')
// printfn "zip_and_unzip_eq_orig x=%A" (zip_and_unzip_eq_orig x)
//
//f [VV [VV [S "12"; S "qwe"]; VV [S "d"]]; VV [VV [S ""; S "ug"]; VV [S ""]]]
T型=
|弦乐
|T表的VV
让l在成功时转置失败=
设为_all_vv_empty x=List.forall(函数vv[]->true | u->false)x
让rec循环acc\总acc\头部acc\尾部=功能
|VV[]::ys->
如果List.isEmpty acc\u head&&is\u all\u vv\u为空,则
如果List.isEmpty acc_total,则failwith“要转置的内部维度中的空输入无效。”
else List.rev acc|U total|>on|U SUCCC
否则将失败()
|VV(x::xs)::ys->循环acc_总计(x::acc_头)(VV xs::acc_尾)ys
|_u::u->on_fail()
| [] ->
将acc_尾与
|循环(VV(List.rev acc\u head)::acc\u总计)[[](List.rev acc\u tail)
|->List.rev acc|u total|>成功
循环[][]l
让rec zip l=
匹配
||::|->转置l(fun |->l)(List.map(函数vvx->zip x | x->x))|>VV
|->failwith“zip的空输入无效。”
让rec解压l=
设为_all_vv x=List.forall(函数vv->真|->假)x
匹配
|VV x->
将x与
|什么时候是转置t(fun->x)id中的所有vv x->let t=List.map(解压>>vv)x
|_u::ux->x
|->failwith“要解压缩的空输入无效。”
|S->failwith“在S上解压调用”
开放式FsCheck
开放系统
让gen_t=
设可变gen\u t=None
让gen_s()=gen.map s Arb.generate
让gen_vv size=gen.nonEmptyListOf(gen_t.Value size)|>gen.map vv
一般
大小与
|0->gen_s()
|当尺寸>0->Gen.oneof[Gen_s();Gen_vv(尺寸-1)]
|用“不可能”表示失败
|>一些
发电价值
|>一般大小
让gen\u t\u list\u unregular=gen.nonEmptyListOf gen\u t
让gen\u t\u list\u regular=gen.map2 list.replicate(gen.choose(1,10))gen\t
类型MyGenerator=
静态成员元组()=Arb.fromGen\u t
静态成员TupleList()=Arb.fromGen\u t\u列表\u常规
仲裁寄存器()
让zip_和解压orig=zip orig |>解压
让zip_和解压_eq_orig orig=zip_和解压orig=orig
//对于常规元组,它会以优异的成绩通过。
Check.One({Config.Quick with EndSize=10},zip_和_unzip_eq_orig)
//对于大小不规则的数组,我不能像预期的那样使其同构。
//设fx=
//设x'=zip x
//printfn“x'=%A“x”
//printfn“解压x'=%A”(解压x')
//打印fn“zip_和解压_eq_orig x=%A”(zip_和解压_eq_orig x)
//
//f[VV[VV[S”12;S“qwe”];VV[S“d”];VV[VV[S”“;S“ug”];VV[S”“]]
不管怎样,我试着,我不知道如何使这对不规则大小的元组同构,我觉得不太可能有人会以不同的方式告诉我,所以我现在把上面的尝试作为一个答案
从好的方面来看,基于上面的测试,我非常确信它对于所有规则大小的元组都应该是同构的。我想这就足够了。与问题中的示例相比,我将代码收紧了一点
这个不规则的压缩和解压问题将成为一个有趣的数学难题