Parametricity
Leo White
Jane Street
February 2016
1/ 59
Parametricity Leo White Jane Street February 2016 1/ 59 - - PowerPoint PPT Presentation
Parametricity Leo White Jane Street February 2016 1/ 59 Parametricity with multiple types. uniformly . from the outside world, parametricity hides details about the outside world from an implementation. 2/ 59 Polymorphism allows a
Leo White
Jane Street
February 2016
1/ 59
▶ Polymorphism allows a single piece of code to be instantiated
with multiple types.
▶ Polymorphism is parametric when all of the instances behave
uniformly.
▶ Where abstraction hides details about an implementation
from the outside world, parametricity hides details about the
2/ 59
3/ 59
4/ 59
(* ∀𝛽.𝛽 → 𝛽 *) let f x = x
5/ 59
(* (∀𝛽.List 𝛽 → 𝐽𝑜𝑢) → 𝐽𝑜𝑢 *) let g h = h [1; 2; 3] + h [1.0; 2.0; 3.0]
Characters 27-30: let g h = h [1; 2; 3] + h [1.0; 2.0; 3.0] ^^^ Error: This expression has type float but an expression was expected of type int
6/ 59
Λ 𝛽::*.𝜇f:𝛽 → Int.𝜇x:𝛽.𝜇y:𝛽. plus (f x) (f y) Λ 𝛽::*.Λ𝛾::*.𝜇f:∀𝛿.𝛿 → Int.𝜇x:𝛽.𝜇y:𝛾. plus (f [𝛽] x) (f [𝛾] y)
7/ 59
Λ 𝛽::*.𝜇f:𝛽 → Int.𝜇x:𝛽.𝜇y:𝛽. plus (f x) (f y) Λ 𝛽::*.Λ𝛾::*.𝜇f:∀𝛿.𝛿 → Int.𝜇x:𝛽.𝜇y:𝛾. plus (f [𝛽] x) (f [𝛾] y)
7/ 59
fun f x y -> f x + f y ∀𝛽::*. (𝛽 → Int) → 𝛽 → 𝛽 → Int ∀𝛽::*.∀𝛾::*. (∀𝛿::*. 𝛿 → Int) → 𝛽 → 𝛾 → Int
8/ 59
(* ∀𝛽.List 𝛽 → 𝐽𝑜𝑢 *) type t = { h : 'a. 'a list -> int } let len = {h = List.length} (* (∀𝛽.List 𝛽 → 𝐽𝑜𝑢) → 𝐽𝑜𝑢 *) let g r = r.h [1; 2; 3] + r.h [1.0; 2.0; 3.0]
9/ 59
f : ∀F::*→*.∀𝛽::*. F 𝛽 → (F 𝛽 → 𝛽) → 𝛽 x : List (Int × Int) f x
10/ 59
𝐺 𝛽 ∼ List(Int × Int) 𝐺 = List 𝛽 = Int × Int 𝐺 = Λ𝛾.List(𝛾 × 𝛾) 𝛽 = Int 𝐺 = Λ𝛾.List(Int × Int)
11/ 59
A set 𝐆 of functions such that: ∀𝐺, 𝐻 ∈ 𝐆. 𝐺 ≠ 𝐻 ⇒ ∀𝑢.𝐺(𝑢) ≠ 𝐻(𝑢)
12/ 59
type 'a t = ('a * 'a) list
13/ 59
type lst = List type opt = Option type ('a, 'f) app = | Lst : 'a list -> ('a, lst) app | Opt : 'a option -> ('a, opt) app ('a, lst)app ≈ 'a list ('a, opt)app ≈ 'a option
14/ 59
type 'f map = { map: 'a 'b. ('a -> 'b) -> ('a, 'f) app -> ('b, 'f) app; } let f : 'b map -> (int, 'b) app -> (string, 'b) app = fun m c -> m.map (fun x -> "Int: " ^ (string_of_int x)) c
15/ 59
let lmap : lst map = {map = fun f (Lst l) -> Lst (List.map f l)} let l = f lmap (Lst [1; 2; 3]) let omap : opt map = {map = fun f (Opt o) -> Opt (Option.map f o)} let o = f omap (Opt (Some 6))
16/ 59
Generalised in the Higher library
17/ 59
18/ 59
module type Eq = sig type t val equal : t -> t -> bool end module type SetS = sig type t type elt val empty : t val is_empty : t -> bool val mem : elt -> t -> bool val add : elt -> t -> t val remove : elt -> t -> t val to_list : t -> elt list end
19/ 59
SetS with type elt = foo
expands to
sig type t type elt = foo val empty : t val is_empty : t -> bool val mem : elt -> t -> bool val add : elt -> t -> t val remove : elt -> t -> t val to_list : t -> elt list end
20/ 59
SetS with type elt := foo
expands to
sig type t val empty : t val is_empty : t -> bool val mem : foo -> t -> bool val add : foo -> t -> t val remove : foo -> t -> t val to_list : t -> foo list end
21/ 59
module Set (E : Eq) : SetS with type elt := E.t = struct type t = E.t list let empty = [] let is_empty = function | [] -> true | _ -> false let rec mem x = function | [] -> false | y :: rest -> if (E.equal x y) then true else mem x rest let add x t = if (mem x t) then t else x :: t
22/ 59
let rec remove x = function | [] -> [] | y :: rest -> if (E.equal x y) then rest else y :: (remove x rest) let to_list t = t end
23/ 59
module IntEq = struct type t = int let equal (x : int) (y : int) = x = y end module IntSet = Set(IntEq)
24/ 59
25/ 59
SetImpl = 𝜇𝛿::*.𝜇𝛽::*. 𝛽 × (𝛽 → Bool) × (𝛿 → 𝛽 → Bool) × (𝛿 → 𝛽 → 𝛽) × (𝛿 → 𝛽 → 𝛽) × (𝛽 → List 𝛿) empty = Λ𝛿::*.Λ𝛽::*.𝜇s:SetImpl 𝛿 𝛽.𝜌1 s is_empty = Λ𝛿::*.Λ𝛽::*.𝜇s:SetImpl 𝛿 𝛽.𝜌2 s mem = Λ𝛿::*.Λ𝛽::*.𝜇s:SetImpl 𝛿 𝛽.𝜌3 s add = Λ𝛿::*.Λ𝛽::*.𝜇s:SetImpl 𝛿 𝛽.𝜌4 s remove = Λ𝛿::*.Λ𝛽::*.𝜇s:SetImpl 𝛿 𝛽.𝜌5 s to_list = Λ𝛿::*.Λ𝛽::*.𝜇s:SetImpl 𝛿 𝛽.𝜌6 s
26/ 59
EqImpl = 𝜇𝛿::*.𝛿 → 𝛿 → Bool equal = Λ𝛿::*.𝜇s:EqImpl 𝛿.s
27/ 59
set_package = Λ𝛿::*. 𝜇eq:EqImpl 𝛿. pack List 𝛿,〈 nil [𝛿], isempty [𝛿], 𝜇n:𝛿.fold [𝛿] [Bool] (𝜇x:𝛿.𝜇y:Bool.or y (equal [𝛿] eq n x)) false, cons [𝛿], 𝜇n:𝛿.fold [𝛿] [List 𝛿] (𝜇x:𝛿.𝜇l:List 𝛿. if (equal [𝛿] eq n x) [List 𝛿] l (cons [𝛿] x l)) (nil [𝛿]), 𝜇l:List 𝛿.l 〉 as ∃𝛽::*.SetImpl 𝛿 𝛽
28/ 59
Γ ⊢ 𝑁 ∶ ∀𝛽∶∶𝐿.𝐵 Γ ⊢ 𝐶 ∶∶ 𝐿 ∀-elim Γ ⊢ 𝑁 [𝐶] ∶ 𝐵[𝛽 ∶= 𝐶]
29/ 59
30/ 59
We can give precise descriptions of parametricity using relations between types.
31/ 59
Given a type 𝑈 with free variables 𝛽, 𝛾1, … , 𝛾𝑜: ∀𝛾1. … ∀𝛾𝑜.∀𝑦 ∶ (∀𝛽.𝑈). ∀𝛿. ∀𝜀. ∀𝜍 ⊂ 𝛿 × 𝜀. 𝑈[𝜍, =𝛾1, … , =𝛾𝑜](𝑦[𝛿], 𝑦[𝜀])
32/ 59
Any value with a universal type must preserve all relations between any two types that it can be instantiated with.
33/ 59
34/ 59
Parametricity applied to ∀𝛽.𝛽 → 𝛽: ∀𝑔 ∶ (∀𝛽.𝛽 → 𝛽). ∀𝛿. ∀𝜀. ∀𝜍 ⊂ 𝛿 × 𝜀. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑣, 𝑤) ⇒ 𝜍(𝑔[𝛿] 𝑣, 𝑔[𝜀] 𝑤)
35/ 59
Defjne a relation is𝑣 to represent being equal to a value 𝑣 ∶ 𝑈: is𝑣(𝑦 ∶ 𝑈, 𝑧 ∶ 𝑈) = (𝑦 =𝑈 𝑣) ∧ (𝑧 =𝑈 𝑣)
36/ 59
∀𝑔 ∶ (∀𝛽.𝛽 → 𝛽). ∀𝛿.∀𝑣 ∶ 𝛿. is𝑣(𝑣, 𝑣) ⇒ is𝑣(𝑔[𝛿]𝑣, 𝑔[𝛿]𝑣)
37/ 59
∀𝑔 ∶ (∀𝛽.𝛽 → 𝛽). ∀𝛿.∀𝑣 ∶ 𝛿. 𝑔[𝛿] 𝑣 =𝛿 𝑣
38/ 59
Parametricity applied to ∀𝛽.List 𝛽 → List 𝛽: ∀𝑔 ∶ (∀𝛽.List 𝛽 → List 𝛽). ∀𝛿. ∀𝜀. ∀𝜍 ⊂ 𝛿 × 𝜀. ∀𝑣 ∶ List 𝛿. ∀𝑤 ∶ List 𝜀. (List 𝛽)[𝜍](𝑣, 𝑤) ⇒ (List 𝛽)[𝜍](𝑔[𝛿] 𝑣, 𝑔[𝜀] 𝑤)
39/ 59
The System F encoding for lists:
List 𝛽 = ∀𝛾. 𝛾 → (𝛽 → 𝛾 → 𝛾) → 𝛾 nil𝛽 = Λ𝛾. 𝜇n:𝛾. 𝜇c:𝛽 → 𝛾 → 𝛾. n cons𝛽 = 𝜇x:𝛽. 𝜇xs:List 𝛽. Λ𝛾. 𝜇n:𝛾. 𝜇c:𝛽 → 𝛾 → 𝛾. c x (xs [𝛾] n c)
40/ 59
The relational substitution of the System F encoding for lists: (List 𝛽)[𝜍] = (𝑦 ∶ List𝐵, 𝑧 ∶ List𝐶). ∀𝛿. ∀𝜀. ∀𝜍′ ⊂ 𝛿 × 𝜀. ∀𝑜 ∶ 𝛿. ∀𝑛 ∶ 𝜀. ∀𝑑 ∶ 𝐵 → 𝛿 → 𝛿. ∀𝑒 ∶ 𝐶 → 𝜀 → 𝜀. 𝜍′(𝑜, 𝑛) ⇒ (∀𝑏 ∶ 𝐵. ∀𝑐 ∶ 𝐶. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑏, 𝑐) ⇒ 𝜍′(𝑣, 𝑤) ⇒ 𝜍′(𝑑𝑏𝑣, 𝑒𝑐𝑤)) ⇒ 𝜍′(𝑦[𝛿]𝑜𝑑, 𝑧[𝜀]𝑛𝑒)
41/ 59
If 𝑦 = 𝑜𝑗𝑚𝐵 and 𝑧 = 𝑜𝑗𝑚𝐶: ∀𝛿. ∀𝜀. ∀𝜍′ ⊂ 𝛿 × 𝜀. ∀𝑜 ∶ 𝛿. ∀𝑛 ∶ 𝜀. ∀𝑑 ∶ 𝐵 → 𝛿 → 𝛿. ∀𝑒 ∶ 𝐶 → 𝜀 → 𝜀. ∀𝑏 ∶ 𝐵.∀𝑣 ∶ 𝛿. ∀𝑐 ∶ 𝐶.∀𝑤 ∶ 𝛿. 𝜍′(𝑜, 𝑛) ⇒ (∀𝑏 ∶ 𝐵. ∀𝑐 ∶ 𝐶. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑏, 𝑐) ⇒ 𝜍′(𝑣, 𝑤) ⇒ 𝜍′(𝑑𝑏𝑣, 𝑒𝑐𝑤)) ⇒ 𝜍′(𝑜𝑗𝑚𝐵[𝛿]𝑜𝑑, 𝑜𝑗𝑚𝐶[𝜀]𝑛𝑒)
42/ 59
If 𝑦 = 𝑜𝑗𝑚𝐵 and 𝑧 = 𝑜𝑗𝑚𝐶: ∀𝛿. ∀𝜀. ∀𝜍′ ⊂ 𝛿 × 𝜀. ∀𝑜 ∶ 𝛿. ∀𝑛 ∶ 𝜀. ∀𝑑 ∶ 𝐵 → 𝛿 → 𝛿. ∀𝑒 ∶ 𝐶 → 𝜀 → 𝜀. ∀𝑏 ∶ 𝐵.∀𝑣 ∶ 𝛿. ∀𝑐 ∶ 𝐶.∀𝑤 ∶ 𝛿. 𝜍′(𝑜, 𝑛) ⇒ (∀𝑏 ∶ 𝐵. ∀𝑐 ∶ 𝐶. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑏, 𝑐) ⇒ 𝜍′(𝑣, 𝑤) ⇒ 𝜍′(𝑑𝑏𝑣, 𝑒𝑐𝑤)) ⇒ 𝜍′(𝑜, 𝑛)
43/ 59
If 𝑦 = 𝑜𝑗𝑚𝐵 and 𝑧 = 𝑜𝑗𝑚𝐶: ∀𝛿. ∀𝜀. ∀𝜍′ ⊂ 𝛿 × 𝜀. ∀𝑜 ∶ 𝛿. ∀𝑛 ∶ 𝜀. ∀𝑑 ∶ 𝐵 → 𝛿 → 𝛿. ∀𝑒 ∶ 𝐶 → 𝜀 → 𝜀. ∀𝑏 ∶ 𝐵.∀𝑣 ∶ 𝛿. ∀𝑐 ∶ 𝐶.∀𝑤 ∶ 𝛿. 𝜍′(𝑜, 𝑛) ⇒ (∀𝑏 ∶ 𝐵. ∀𝑐 ∶ 𝐶. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑏, 𝑐) ⇒ 𝜍′(𝑣, 𝑤) ⇒ 𝜍′(𝑑𝑏𝑣, 𝑒𝑐𝑤)) ⇒ 𝜍′(𝑜, 𝑛)
44/ 59
If 𝑦 = 𝑑𝑝𝑜𝑡𝐵 𝑗𝑚 and 𝑧 = 𝑑𝑝𝑜𝑡𝐶 𝑘𝑙: ∀𝛿. ∀𝜀. ∀𝜍′ ⊂ 𝛿 × 𝜀. ∀𝑜 ∶ 𝛿. ∀𝑛 ∶ 𝜀. ∀𝑑 ∶ 𝐵 → 𝛿 → 𝛿. ∀𝑒 ∶ 𝐶 → 𝜀 → 𝜀. 𝜍′(𝑜, 𝑛) ⇒ (∀𝑏 ∶ 𝐵. ∀𝑐 ∶ 𝐶. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑏, 𝑐) ⇒ 𝜍′(𝑣, 𝑤) ⇒ 𝜍′(𝑑𝑏𝑣, 𝑒𝑐𝑤)) ⇒ 𝜍′(𝑑𝑝𝑜𝑡𝐵[𝛿]𝑗𝑚𝑜𝑑, 𝑑𝑝𝑜𝑡𝐶[𝜀]𝑘𝑙𝑛𝑒)
45/ 59
If 𝑦 = 𝑑𝑝𝑜𝑡𝐵 𝑗𝑚 and 𝑧 = 𝑑𝑝𝑜𝑡𝐶 𝑘𝑙: ∀𝛿. ∀𝜀. ∀𝜍′ ⊂ 𝛿 × 𝜀. ∀𝑜 ∶ 𝛿. ∀𝑛 ∶ 𝜀. ∀𝑑 ∶ 𝐵 → 𝛿 → 𝛿. ∀𝑒 ∶ 𝐶 → 𝜀 → 𝜀. 𝜍′(𝑜, 𝑛) ⇒ (∀𝑏 ∶ 𝐵. ∀𝑐 ∶ 𝐶. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑏, 𝑐) ⇒ 𝜍′(𝑣, 𝑤) ⇒ 𝜍′(𝑑𝑏𝑣, 𝑒𝑐𝑤)) ⇒ 𝜍′(𝑑 𝑗 (𝑚[𝛿] 𝑜 𝑑), 𝑒 𝑘 (𝑙[𝛿] 𝑛 𝑒))
46/ 59
If 𝑦 = 𝑑𝑝𝑜𝑡𝐵 𝑗𝑚 and 𝑧 = 𝑑𝑝𝑜𝑡𝐶 𝑘𝑙: ∀𝛿. ∀𝜀. ∀𝜍′ ⊂ 𝛿 × 𝜀. ∀𝑜 ∶ 𝛿. ∀𝑛 ∶ 𝜀. ∀𝑑 ∶ 𝐵 → 𝛿 → 𝛿. ∀𝑒 ∶ 𝐶 → 𝜀 → 𝜀. 𝜍′(𝑜, 𝑛) ⇒ (∀𝑏 ∶ 𝐵. ∀𝑐 ∶ 𝐶. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑏, 𝑐) ⇒ 𝜍′(𝑣, 𝑤) ⇒ 𝜍′(𝑑𝑏𝑣, 𝑒𝑐𝑤)) ⇒ 𝜍′(𝑑𝑗(𝑚[𝛿]𝑜𝑑), 𝑒𝑘(𝑙[𝛿]𝑛𝑒))
47/ 59
If 𝑦 = 𝑑𝑝𝑜𝑡𝐵 𝑗𝑚 and 𝑧 = 𝑑𝑝𝑜𝑡𝐶 𝑘𝑙: ∀𝛿. ∀𝜀. ∀𝜍′ ⊂ 𝛿 × 𝜀. ∀𝑜 ∶ 𝛿. ∀𝑛 ∶ 𝜀. ∀𝑑 ∶ 𝐵 → 𝛿 → 𝛿. ∀𝑒 ∶ 𝐶 → 𝜀 → 𝜀. 𝜍′(𝑜, 𝑛) ⇒ (∀𝑏 ∶ 𝐵. ∀𝑐 ∶ 𝐶. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. 𝜍(𝑏, 𝑐) ⇒ 𝜍′(𝑣, 𝑤) ⇒ 𝜍′(𝑑𝑏𝑣, 𝑒𝑐𝑤)) ⇒ 𝜍(𝑗, 𝑘) ∧ 𝜍′(𝑚[𝛿]𝑜𝑑, 𝑙[𝛿]𝑛𝑒)
48/ 59
The relational substitution of the System F encoding for lists: (List 𝛽)[𝜍](𝑦 ∶ List 𝐵, 𝑧 ∶ List 𝐶) = ⎧ { ⎨ { ⎩ 𝜍(𝑗, 𝑘) ∧ (List 𝛽)[𝜍](𝑚, 𝑙), 𝑦 = 𝑑𝑝𝑜𝑡𝐵 𝑗𝑚 ∧ 𝑧 = 𝑑𝑝𝑜𝑡𝐶 𝑘𝑙 𝑢𝑠𝑣𝑓, 𝑦 = 𝑜𝑗𝑚𝐵 ∧ 𝑧 = 𝑜𝑗𝑚𝐶 𝑔𝑏𝑚𝑡𝑓, 𝑝𝑢ℎ𝑓𝑠𝑥𝑗𝑡𝑓
49/ 59
Defjne a relation ⟨⟩ to represent a function ∶ 𝐵 → 𝐶 ⟨⟩(𝑦 ∶ 𝐵, 𝑧 ∶ 𝐶) = ( 𝑦 =𝐶 𝑧)
50/ 59
Apply the relational substitution for lists to ⟨⟩: (List 𝛽)[⟨⟩](𝑦 ∶ List 𝐵, 𝑧 ∶ List 𝐶) = ⎧ { ⎨ { ⎩ 𝑗 =𝐶 𝑘 ∧ (List 𝛽)[⟨⟩](𝑚, 𝑙), 𝑦 = 𝑑𝑝𝑜𝑡𝐵 𝑗𝑚 ∧ 𝑧 = 𝑑𝑝𝑜𝑡𝐶 𝑘𝑙 𝑢𝑠𝑣𝑓, 𝑦 = 𝑜𝑗𝑚𝐵 ∧ 𝑧 = 𝑜𝑗𝑚𝐶 𝑔𝑏𝑚𝑡𝑓, 𝑝𝑢ℎ𝑓𝑠𝑥𝑗𝑡𝑓
51/ 59
Apply the relational substitution for lists to ⟨⟩: (List 𝛽)[⟨⟩](𝑦𝑡 ∶ List 𝐵, 𝑧𝑡 ∶ List 𝐶) = map 𝑦𝑡 =List 𝐶 𝑧𝑡
52/ 59
A free theorem for ∀𝛽.List 𝛽 → List 𝛽: ∀𝑔 ∶ (∀𝛽.List 𝛽 → List 𝛽). ∀𝛿. ∀𝜀. ∀ ∶ 𝛿 → 𝜀 ∀𝑣 ∶ List 𝛿. ∀𝑤 ∶ List 𝜀. map[𝛿][𝜀] (𝑔[𝛿] 𝑣) = 𝑔[𝜀] (map[𝛿][𝜀] 𝑣)
53/ 59
54/ 59
let f (x : 'a) : 'a = Printf.printf "Launch missiles\n"; x let f (x : 'a) : 'a = raise Exit let rec f (x : 'a) : 'a = f x
55/ 59
Parametricity applied to ∀𝛽.𝛽 → 𝛽 → Bool: ∀𝑔 ∶ (∀𝛽.𝛽 → 𝛽 → Bool). ∀𝛿. ∀𝜀. ∀𝜍 ⊂ 𝛿 × 𝜀. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. ∀𝑣′ ∶ 𝛿. ∀𝑤′ ∶ 𝜀. 𝜍(𝑣, 𝑤) ⇒ 𝜍(𝑣′, 𝑤′) ⇒ 𝐶𝑝𝑝𝑚[𝜍](𝑔[𝛿] 𝑣 𝑣′, 𝑔[𝜀]𝑤𝑤′)
56/ 59
Parametricity applied to ∀𝛽.𝛽 → 𝛽 → Bool: ∀𝑔 ∶ (∀𝛽.𝛽 → 𝛽 → Bool). ∀𝛿. ∀𝜀. ∀𝜍 ⊂ 𝛿 × 𝜀. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. ∀𝑣′ ∶ 𝛿. ∀𝑤′ ∶ 𝜀. 𝜍(𝑣, 𝑤) ⇒ 𝜍(𝑣′, 𝑤′) ⇒ (𝑔[𝛿] 𝑣 𝑣′ =𝐶𝑝𝑝𝑚 𝑔[𝜀]𝑤𝑤′)
57/ 59
∀𝑔 ∶ (∀𝛽.𝛽 → 𝛽 → Bool). ∀𝛿. ∀𝜀. ∀𝑣 ∶ 𝛿. ∀𝑤 ∶ 𝜀. ∀𝑣′ ∶ 𝛿. ∀𝑤′ ∶ 𝜀. (𝑔[𝛿] 𝑣 𝑣′ =𝐶𝑝𝑝𝑚 𝑔[𝜀]𝑤𝑤′)
58/ 59
val (=) : 'a -> 'a -> bool
59/ 59