machine instructions) L O A D B R 1 0 x F F 0 0 L O A D H R 2 0 x F F 0 0 L O A D R 3 0 x F F 0 0 Adding context c h a r * l a b e l = [ ' a ' , ' b ' ] User defined types S T R U C T U R E / i t e m / I N T E G E R i d C H A R A C T E R ( L E N = 2 0 0 ) R E A L p r i c e E N D S T R U C T U R E
billion‑dollar mistake…At that time, I was designing the first comprehensive type system for references in an object‑oriented language. My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. ‑‑ Tony Hoare, inventor of ALGOL W
weakly types languages Type safe, memory safe Functional languages Object oriented languages Interfaces, generics, immutable collections, constrained types, sum types
t P e r s o n { l e t f i r s t N a m e : S t r i n g l e t s u r n a m e : S t r i n g l e t h e i g h t : U I n t 8 } c l a s s P e r s o n { S t r i n g f i r s t N a m e ; S t r i n g s u r n a m e ; i n t h e i g h t ; } Java not pure product types because of nullability.
F o o { l e t x : B o o l l e t y : U i n t 8 } {(x, y) : x ∈ bool, y ∈ uint8} Interpretation: There are two possible values of the x b o o l and 256 possible values of the y u i n t 8 . The struct F o o has 512 possible values or the product of the possible values of it's components In languages with nulls {(x, y) : x ∈ {bool, null}, y ∈ {uint8, null}}
F o o { x 1 : t y p e 1 x 2 : t y p e 2 x 3 : t y p e 3 . . . . . . x N : t y p e N } Possible values are Foo = type1 ⋅ type2 ⋅ type3 ⋅ ... ⋅ typeN N (Foo) = N (type ) pv i=0 ∏ n pv i
underutilized pattern e n u m F o o { c a s e x ( B o o l ) c a s e y ( U i n t 8 ) } l e t a = F o o . x ( t r u e ) l e t b = F o o . y ( 1 2 ) l e t v a l s = [ a , b ] / / v a l s o f t y p e F o o The type is a sum of possible values. If x can have 2 values and y can have 256 possible values ‑ F o o can have 258 values Foo = bool + uint8
o { c a s e x 1 ( t y p e 1 ) c a s e x 2 ( t y p e 2 ) . . . c a s e x N ( t y p e N ) } Possible values: Foo = type + type + ... + type N (Foo) = N (type ) 1 2 n pv i=0 ∑ n pv i
t w o r k C a l l . d i d R e s p o n d ( h a n d l e r : { r e s u l t , e r r o r i n i f r e s u l t ! = n i l { / / h a n d l e s u c c e s s } i f e r r o r ! = n i l { / / h a n d l e e r r o r } / / ? ? ? ? } What about the third case if result and error are null. Possible values are r e s u l t = n u l l , e r r o r = n u l l r e s u l t = s o m e , e r r o r = n u l l r e s u l t = n u l l , e r r o r = s o m e r e s u l t = s o m e , e r r o r = s o m e This is a product type, serving a sum type purpose
m R e s u l t { c a s e s u c c e s s ( S t r i n g ) c a s e e r r o r ( E r r o r ) } n e t w o r k C a l l . d i d R e s p o n d ( h a n d l e r : { r e s u l t i n s w i t c h r e s u l t { c a s e . s u c c e s s ( l e t d a t a ) : / / h a n d l e s u c c e s s c a s e . e r r o r ( l e t e r r o r ) : / / h a n d l e e r r o r } } ) Benefits are explicit case handling exhaustiveness number of possible values matches reality
are just sum types e n u m O p t i o n a l < T > { c a s e s o m e ( T ) c a s e n o n e } the values are N [Optional(T)] = N (T) + 1 All values that type T can have, plus the value n o n e meaning that the value was not assigned pv pv
they actually hold value No `NullPointerException`` l e t a = O p t i o n a l < S t r i n g > . n o n e l e t b = O p t i o n a l < S t r i n g > . s o m e ( " a b c " ) l e t a r r = [ a , b ] a r r . f o r E a c h { i t e m i n i t e m . l e n g t h / / c a n ' t d o i t s w i t c h i t e m { c a s e . s o m e ( l e t v a l u e ) : v a l u e . l e n g t h / / h a n d l e v a l u e c a s e . n o n e / / h a n d l e n o v a l u e } }
t a : S t r i n g ? = n i l / / S t r i n g ? m e a n s t y p e i s / / O p t i o n a l < S t r i n g > i f l e t b = a { b . l e n g t h / / b i s ' u n w r a p p e d ' a } g u a r d l e t c = a e l s e { f a t a l E r r o r ( " n o v a l u e " ) } c . l e n g t h / / c u n w r a p p e d h e r e a . l e n g t h / / s y n t a x e r r o r l e t d = a ? . l e n g t h / / c o m p l i e s - r e t u r n s O p t i o n a l < I n t > d ? . i s Z e r o / / R e t u r n s O p t i o n a l < B o o l > - o p t i o n a l s p r o p a g a t e / / c a n ' t a c c e s s w i t h o u t u n w r a p p i n g Accessing uninitialized optionals changed from runtime to compile time. Major safety benefits!
t e r { c a s e g e t U s e r ( i d : I n t ) c a s e g e t W e a t h e r ( l o c a t i o n : S t r i n g ) v a r b a s e P a t h = " h t t p s : / / m y S i t e . c o m / a p i / v 1 / " v a r p a t h : S t r i n g { s w i t c h s e l f { c a s e . g e t U s e r ( l e t i d ) : r e t u r n b a s e P a t h + " u s e r / \ ( i d ) " c a s e . g e t W e a t h e r ( l e t l o c a t i o n ) : r e t u r n b a s e P a t h + " w e a t h e r ? l o c a t i o n = \ ( l o c a t i o n ) " } } }
a t r e e i n d i r e c t e n u m T r e e { c a s e n o d e ( I n t , l : T r e e , r : T r e e ) c a s e l e a f ( I n t ) } / / D e c l a r e a l i s t i n d i r e c t e n u m L i s t { c a s e n o d e ( I n t , L i s t ) c a s e l e a f ( I n t ) }
r e e . n o d e ( 1 2 , l : . l e a f ( 1 1 ) , r : . n o d e ( 1 3 , l : . n o d e ( 5 5 , l : . l e a f ( 1 1 ) , r : . l e a f ( 7 7 ) ) , r : . l e a f ( 1 3 ) ) ) t r e e . p r e t t y / / 1 2 : { 1 1 , 1 3 : { 5 5 : { 1 1 , 7 7 } , 1 3 } } l e t l i s t = L i s t . n o d e ( 1 , . n o d e ( 2 , . n o d e ( 3 , . n o d e ( 4 ) ) ) )
polymorphism less ad‑hoc https://people.csail.mit.edu/dnj/teaching/6898/papers/wadler88 .pdf Advanced Topics in Types and Programming Languages https://www.cis.upenn.edu/~bcpierce/attapl/