package sherlodoc
Search engine for OCaml documentation
Install
Dune Dependency
Authors
Maintainers
Sources
odoc-3.1.0.tbz
sha256=355b3cfff4934903cbaed8b51ce35e333e8609932d230294200a9f2d42ffa914
sha512=f78318d0a16164a9cd16ee02f611c2e00d32b772fe38e992d6db6ec94b1c00cd9c377fbfe64031b8f245e57b2f3aac9364108327e7f1693533ddcff94c476e05
doc/src/sherlodoc.query/type_distance.ml.html
Source file type_distance.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
type step = | Type of string | Poly | Any | Arrow_left | Arrow_right | Product of { pos : int ; length : int } | Argument of { pos : int ; length : int } module Sign = Db.Type_polarity.Sign type t = step list list let rev_concat lst = List.fold_left (fun acc xs -> List.rev_append xs acc) [] lst let rec paths_of_type ~prefix t = match t with | Db.Typexpr.Poly _ -> [ Poly :: prefix ] | Any -> [ Any :: prefix ] | Arrow (a, b) -> let prefix_left = Arrow_left :: prefix in let prefix_right = Arrow_right :: prefix in List.rev_append (paths_of_type ~prefix:prefix_left a) (paths_of_type ~prefix:prefix_right b) | Constr (name, args) -> let prefix = Type name :: prefix in begin match args with | [] -> [ prefix ] | _ -> let length = List.length args in rev_concat @@ List.mapi (fun i arg -> let prefix = Argument { pos = i; length } :: prefix in paths_of_type ~prefix arg) args end | Tuple args -> let length = List.length args in rev_concat @@ List.mapi (fun i arg -> let prefix = Product { pos = i; length } :: prefix in paths_of_type ~prefix arg) @@ args | Unhandled -> [] let paths_of_type t = List.map List.rev @@ paths_of_type ~prefix:[] t (* *) let skip_entry _ = 10 let distance xs ys = let len_xs = List.length xs in let len_ys = List.length ys in let cache = Array.make_matrix (1 + len_xs) (1 + len_ys) (-1) in let inv = Db.Type_polarity.Sign.not in let rec memo ~xsgn ~ysgn i j xs ys = let r = cache.(i).(j) in if r >= 0 then r else begin let r = go ~xsgn ~ysgn i j xs ys in cache.(i).(j) <- r ; r end and go ~xsgn ~ysgn i j xs ys = match xs, ys with | [], [] -> 0 | [], _ -> 0 | [ Any ], _ when xsgn = ysgn -> 0 | [ Poly ], [ (Any | Poly) ] when xsgn = ysgn -> 0 | Arrow_left :: xs, Arrow_left :: ys -> memo ~xsgn:(inv xsgn) ~ysgn:(inv ysgn) (i + 1) (j + 1) xs ys | x :: xs, y :: ys when x = y && xsgn = ysgn -> memo ~xsgn ~ysgn (i + 1) (j + 1) xs ys | _, Arrow_left :: ys -> 1 + memo ~xsgn ~ysgn:(inv ysgn) i (j + 1) xs ys | Arrow_left :: xs, _ -> 1 + memo ~xsgn:(inv xsgn) ~ysgn (i + 1) j xs ys | _, Arrow_right :: ys -> memo ~xsgn ~ysgn i (j + 1) xs ys | Arrow_right :: xs, _ -> memo ~xsgn ~ysgn (i + 1) j xs ys | _, [] -> 10_000 | Product _ :: xs, Product _ :: ys -> 1 + memo ~xsgn ~ysgn (i + 1) (j + 1) xs ys | Argument _ :: xs, Argument _ :: ys -> 1 + memo ~xsgn ~ysgn (i + 1) (j + 1) xs ys | Product _ :: xs, ys -> 1 + memo ~xsgn ~ysgn (i + 1) j xs ys | xs, Product _ :: ys -> 1 + memo ~xsgn ~ysgn i (j + 1) xs ys | Type x :: xs', Type y :: ys' when xsgn = ysgn -> begin let skip_y = skip_entry y in match Name_cost.best_match ~sub:x y with | None -> skip_y + memo ~xsgn ~ysgn i (j + 1) xs ys' | Some (_, cost) -> (cost / 3) + memo ~xsgn ~ysgn (i + 1) (j + 1) xs' ys' end | xs, Type y :: ys' -> skip_entry y + memo ~xsgn ~ysgn i (j + 1) xs ys' | xs, Argument _ :: ys' -> memo ~xsgn ~ysgn i (j + 1) xs ys' | _, (Any | Poly) :: _ -> 10_000 in let pos = Db.Type_polarity.Sign.Pos in go ~xsgn:pos ~ysgn:pos 0 0 xs ys let minimize = function | [] -> 0 | arr -> let used = Array.make (List.length (List.hd arr)) false in let arr = Array.map (fun lst -> let lst = List.mapi (fun i x -> x, i) lst in List.sort Stdlib.compare lst) @@ Array.of_list arr in Array.sort (fun xs ys -> Stdlib.compare xs ys) arr ; let heuristics = Array.make (Array.length arr + 1) 0 in for i = Array.length heuristics - 2 downto 0 do let best = fst (List.hd arr.(i)) in heuristics.(i) <- heuristics.(i + 1) + best done ; let best = ref 1000 in let limit = ref 0 in let rec go rem acc i = incr limit ; if !limit > 10_000 then false else if rem <= 0 then begin (* entry type is smaller than query type *) let score = acc + (1000 * (Array.length arr - i)) in best := min score !best ; true end else if i >= Array.length arr then begin (* query type is smaller than entry type *) let score = acc + (5 * rem) in best := min score !best ; true end else if acc + heuristics.(i) >= !best then true else begin let rec find = function | [] -> true | (cost, j) :: rest -> let continue = if used.(j) then true else begin used.(j) <- true ; let continue = go (rem - 1) (acc + cost) (i + 1) in used.(j) <- false ; continue end in if continue then find rest else false in find arr.(i) end in let _ = go (Array.length used) 0 0 in !best let v ~query_paths ~entry = let entry_paths = paths_of_type entry in match entry_paths, query_paths with | _, [] | [], _ -> 0 | _ -> let arr = List.map (fun p -> List.map (distance p) entry_paths) query_paths in minimize arr
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>