union types and literal singleton types in scala (and typescript)

40
joostde-vriesname joost-de-vries jouke UNION TYPES & LITERAL SINGLETON TYPES ING Zandkasteel - Amsterdam

Upload: joost-de-vries

Post on 14-Apr-2017

265 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Union Types and Literal Singleton Types in Scala (and Typescript)

joost@de-vries․namejoost-de-vriesjouke

UNIONTYPES&

LITERALSINGLETONTYPES

INGZandkasteel-Amsterdam

Page 2: Union Types and Literal Singleton Types in Scala (and Typescript)

THREEACTS1. Whatarethey?Whyaretheyuseful?

2. HowtousetheminScalarightnow

3. UsingtheminDotty

Page 3: Union Types and Literal Singleton Types in Scala (and Typescript)

①UNIONTYPES&

LITERALSINGLETONTYPESWhatarethey?

Whyaretheyuseful?

Page 4: Union Types and Literal Singleton Types in Scala (and Typescript)

LITERALSINGLETONTYPES

Weknowsingletontypes:everyscalasingletonhasatype

objectS{

}

defg(s:S.type)=s//g:(s:S.type)S$

Asingletontypeisatypewithjustoneinstance

Page 5: Union Types and Literal Singleton Types in Scala (and Typescript)

LITERALSINGLETONTYPES

Butwhatwe'dliketoexpressisliteralsintypes.ForinstanceinSpire

forAll{x:Ranged[Int,1,100]=>valn:Int=x.value//guaranteedtobe1to100}

Page 6: Union Types and Literal Singleton Types in Scala (and Typescript)

LITERALSINGLETONTYPESAndinScala.js

Thesearesomeofthemotivationsmentionedin

traitHTMLCanvasElementextendsHTMLElement{defgetContext(contextId:String):AnydefgetContext(contextId:"2d"):CanvasRenderingContext2D}

valanyContext=canvas.getContext("webgl")valcontext2D=canvas.getConttext("2d")

SIP-42

Page 7: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPES

It'sorfortypes

Terminologyfromsettheory

Page 8: Union Types and Literal Singleton Types in Scala (and Typescript)

INTERSECTIONTYPES

It'sandfortypes

Page 9: Union Types and Literal Singleton Types in Scala (and Typescript)

TRANSLATION

And ⇒ Or

∧ ⇒ ∨

Conjunction ⇒ Disjunction

Intersection ⇒ Union

Co-product ⇒ Tuple/Product/HList

Canbeconfusing

Page 10: Union Types and Literal Singleton Types in Scala (and Typescript)

INTERSECTIONTYPESWealmosthaveintersectiontypesinScala

Usuallyusedformixins

ButAwithBdoesn'tequalBwithA

valloggablePerson=newPersonwithLoggable()

Page 11: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESAREUSEFUL

It'sEither[A,B]

foranynroftypes

withoutboxing

/***If'padding'isastring,then'padding'isappendedtotheleftside.*If'padding'isanumber,thenthatnumberofspacesisaddedtotheleftside.*/functionpadLeft(value:string,padding:string|number)={//...}padLeft("hello",true)//doesn'tcompile

Page 12: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPES

Eithercan'tdothat

interfaceBird{fly()layEggs()}

interfaceFish{swim()layEggs()}

functiongetSmallPet():Fish|Bird{/*...*/}

letpet=getSmallPet()pet.layEggs()//okay//pet.swim()doesn'tcompile

Page 13: Union Types and Literal Singleton Types in Scala (and Typescript)

USEUNIONTYPESFORNONNULLABLETYPES

letfoo:string=null//Error!

letfoo:string|null=null//Okay!

UsingthestrictNullCheckcompileroption

Page 14: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONOFLITERALTYPES

Whatanawesomeway

toexpressenumerations!

typeDigit=0|1|2|3|4|5|6|7|8|9;letnums:Digit[]=[1,2,4,8];

nums.push(16)//Doesn'tcompile

Page 15: Union Types and Literal Singleton Types in Scala (and Typescript)

②UNIONTYPES&

LITERALSINGLETONTYPESHowtousetheminScalarightnow

Page 16: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESINSCALARIGHTNOW

Page 17: Union Types and Literal Singleton Types in Scala (and Typescript)

PROGRAMMINGISLIKELOGICif it is thursday there's a scala meetingif there's a scala meeting the term 'monad' will come upit is thursday-------------------------------------------------------the term 'monad' will come up

Page 18: Union Types and Literal Singleton Types in Scala (and Typescript)

PROGRAMMINGISLIKELOGICit is thursday → there's a scala meetingthere's a scala meeting → the term 'monad' will come upit is thursday-------------------------------------------------------the term 'monad' will come up

Page 19: Union Types and Literal Singleton Types in Scala (and Typescript)

PROGRAMMINGISLIKELOGICThursday → ScalaMeetingScalaMeeting → MonadThursday-------------------------------------------------------Monad

Page 20: Union Types and Literal Singleton Types in Scala (and Typescript)

PROGRAMMINGISLIKELOGIC

valf:Thursday⇒ScalaMeetingvalg:ScalaMeeting⇒Monadvalt:Thursday

valm:Monad=g(f(t))

Theimplementationofthefunctionistheproofofitstype

Page 21: Union Types and Literal Singleton Types in Scala (and Typescript)

INLOGICWecancreateoroutofand,not

AorB⇔not(notAandnotB)

Page 22: Union Types and Literal Singleton Types in Scala (and Typescript)

INLOGICWecancreateoroutofand,not

A⋁B⇔¬(¬A⋀¬B)

Page 23: Union Types and Literal Singleton Types in Scala (and Typescript)

SCALATOLOGIC(AwithB)<:A (A∧B)⇒A

(AwithB)<:B (A∧B)⇒B

A<:(A∨B) A⇒(A∨B)B<:(A∨B) B⇒(A∨B)

Page 24: Union Types and Literal Singleton Types in Scala (and Typescript)

CREATINGORFROMAND,NOT

(A∨B)⇔¬(¬A∧¬B)becomes

(A∨B)=:=¬[¬[A]with¬[B]]

Sowheredowegetnot?

Page 25: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESIN3LINESOFCODE

IsMilesSabincoolorwhat?

AninstanceofA<:<BwitnessesthatAisasubtypeofB

type¬[A]=A=>Nothing

type∨[T,U]=¬[¬[T]with¬[U]]

type¬¬[A]=¬[¬[A]]

implicitly[¬¬[Int]<:<(Int∨String)]//res0:<:<[¬¬[Int],∨[Int,String]]=<function1>

implicitly[¬¬[Double]<:<(Int∨String)]//error:Cannotprovethat¬¬[Double]<:<∨[Int,String].

Page 26: Union Types and Literal Singleton Types in Scala (and Typescript)

LET'SUSEOURUNIONTYPE

defpadLeft[T](value:String,padding:T)(implicitev:¬¬[T]<:<(Int∨String))="somestring"

padLeft("hello",3)//compiles

//padLeft("hello",true)doesn'tcompile://error:CannotprovethatTest5.¬[Test5.¬[Boolean']]<:<Test5.∨[Int,String].//padLeft("hello",true)

Page 27: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESIN3LINESOFCODE

PuttheevidenceinapathdependenttypeλspecifictoourtypesTandU

type|∨|[T,U]={typeλ[X]=¬¬[X]<:<(T∨U)}

defpadLeft2[T](value:String,padding:T)(implicitev:(Int|∨|String)#λ[T])="somestring"

Page 28: Union Types and Literal Singleton Types in Scala (and Typescript)

USETHEIMPLEMENTATIONINSHAPELESS

UniontypesarecalledCoproductsinShapeless

Literaltypes(peanonumbers)areusedinSizedcollections

Page 29: Union Types and Literal Singleton Types in Scala (and Typescript)

③UNIONTYPES&

LITERALSINGLETONTYPESUsingtheminDotty

Page 30: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPES

Whatwewanttoachieve

/***If'padding'isastring,then'padding'isappendedtotheleftside.*If'padding'isanumber,thenthatnumberofspacesisaddedtotheleftside.*/functionpadLeft(value:string,padding:string|number)={//...}padLeft("hello",true)//doesn'tcompile

Page 31: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESINDOTTY/***If'padding'isastring,then'padding'isappendedtotheleftside.*If'padding'isanumber,thenthatnumberofspacesisaddedtotheleftside.*/defpadLeft(value:String,padding:String|Int)={//...}padLeft("hello",true)

//error:typemismatch://found:Boolean(true)//required:String|Int//padLeft("hello",true)//^

Cool!

Page 32: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESINDOTTYclassBird(){deffly()={}deflayEggs()={}}

classFish(){defswim()={}deflayEggs()={}}

defgetSmallPet()=if(newRandom().nextBoolean)newFish()elsenewBird()

valp=getSmallPet()

p.layEggs()error:valuelayEggsisnotamemberofObject(p)p.layEggs()^

Huh?

Page 33: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESINDOTTYimportdotty.language.keepUnions

classBird(){deffly()={}deflayEggs()={}}

classFish(){defswim()={}deflayEggs()={}}

defgetSmallPet()=if(newRandom().nextBoolean)newFish()elsenewBird()

valp=getSmallPet()

p.layEggs()//compiles Becauseofperformance

oflargenrsofunionedtypes

Page 34: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESPLUSSINGLETONTYPESINDOTTY

objectMondayobjectTuesday//...

typeWeekday=Monday.type|Tuesday.type|Wednesday.type|Thursday.type|Friday.typetypeWeekend=Saturday.type|Sunday.typetypeAnyDay=Weekday|Weekend

println("Mondayisweekday:"+Monday.isInstanceOf[Weekday])println("Saturdayisweekend:"+Saturday.isInstanceOf[Weekend])println("Sundayisweekday:"+Sunday.isInstanceOf[Weekday])

(Monday:AnyDay)match{case_:Weekend=>println("shouldn'tmatch")}

Worksagainsince7daysago

Page 35: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESPLUSSINGLETONTYPESINDOTTY

Bug!

typeWeekday="Monday"|"Tuesday"|"Wednesday"|"Thursday"|"Friday"typeWeekend="Saturday"|"Sunday"typeAnyDay=Weekday|Weekend

vald:Weekday="Sunday"//compiles?!

Currentlyunionsofliteraltypesarewidened

toStringinthiscase

Page 36: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESPLUSSINGLETONTYPESINDOTTY

Sameproblem

typeDigit=0|1|2|3|4|5|6|7|8|9

defformat(ds:Seq[Digit])={}

format(Seq(4,9,13))//shouldn'tcompile

Page 37: Union Types and Literal Singleton Types in Scala (and Typescript)

UNIONTYPESPLUSSINGLETONTYPESINDOTTY

Page 38: Union Types and Literal Singleton Types in Scala (and Typescript)

DOTTYItreallyis,likethesitesays,prebeta

It'seasytotryoutwiththesbt-dottyplugin

Althoughtherearenosnapshotbuildsyet

But:syntaxhighlightingintheconsole!

Page 39: Union Types and Literal Singleton Types in Scala (and Typescript)

Kleurtjes!

Page 40: Union Types and Literal Singleton Types in Scala (and Typescript)

Fin