F# for Scala Developers Walking into the dark side meets Scal a and F # Madrid Meetup groups
How much do Scala and F# look alike? Bring (non-strict) Functional Programming to Java and .NET Ful compatibility with their host platforms Built-in functional libraries Static safety with type inference Mostly expression based (side-effects also al owed) Open source projects with vibrant communities
How much do Scala and F# differ? Scala Embraces both Object Oriented and Functional Programming Designed not to scare OOP developers: curly-brace Very powerful and flexible syntax Very rich class system Language team works separately from Java team
How much do Scala and F# differ? F# Multi-paradigm but functional-first Inherited from Ocaml: indentation sensitive Less flexible syntax, more focused on consistency Three flavors: project (.fs), script (.fsx) and signature (.fsi) files Language team works together (more or less) with .NET team Functional features like generics and tail-cal instructions are native to the platform
F# As in Scala, break and continue are missing from the language. Recursion or stream functions are preferred. 1: IRU LQGH[ WR GR 2: SULQWIQ L WLPHV LV L LQGH[ LQGH[ 3: 4: OHW PXWDEOH LQGH[ ZKLOH LQGH[ GR 5: SULQWIQ L WLPHV LV L LQGH[ LQGH[ 6: LQGH[ LQGH[ 7:
F# As seen above, functions in F# are usual y contained in modules (curried by default) Optional and rest parameters are only accepted in non-curried class methods 1: RSHQ 6\VWHP 2: 3: W\SH 0\&ODVV 4: VWDWLF PHPEHU 0\)XQFWLRQ "[ "\ GHIDXOW$UJ [ GHIDXOW$UJ \ 5: VWDWLF PHPEHU 0\)XQFWLRQ > 3DUDP$UUD\!@ UHVW LQW DUUD\ 6: $UUD\ UHGXFH UHVW 7: 8: 0\&ODVV 0\)XQFWLRQ \ 9: 0\&ODVV 0\)XQFWLRQ 10:
Classes Scala Classes are very powerful in Scala and different from F#: Singleton objects Traits and abstract types Compound types and mixins
F# F# doesn't focus on classes Their main purpose is compatibility with .NET Base Class Library Mostly same functionality as C# with different Syntax and some additional features (like primary constructors) Interfaces are just abstract classes without default method implementations No mixins, only multiple interface implementation is possible (extension methods are al owed) Object Expressions al ow dynamic implementation of interfaces
F# Exhaustive Active Patterns 1: OHW _(YHQ_2GG_ L 2: LI L WKHQ (YHQ HOVH 2GG 3: 4: PDWFK ZLWK (YHQ ! +HOOR _ 2GG ! *RRGE\H _! SULQWIQ V 5: F# Partial Active Pattern 1: OHW _,QWHJHU_B_ VWU VWULQJ 2: PDWFK 6\VWHP ,QW 7U\3DUVH VWU ZLWK 3: _ WUXH L ! 6RPH L _ IDOVH B ! 1RQH 4: OHW _)ORDW_B_ VWU VWULQJ 5: PDWFK 6\VWHP 'RXEOH 7U\3DUVH VWU ZLWK 6: _ WUXH I ! 6RPH I _ IDOVH B ! 1RQH 7: 8: PDWFK +ROD ZLWK 9: _ ,QWHJHU L ! SULQWIQ G ,QWHJHU L _ )ORDW I ! SULQWIQ I )ORDWLQJ SRLQW I 10: $SSHDVH WKH FRPSLOHU 11: _ B DV VWU ! SULQWIQ V 1RW PDWFKHG VWU 12: 13:
F# Parameterized Active Patterns Specializing the pattern by passing extra parameters 1: RSHQ 6\VWHP 7H[W 5HJXODU([SUHVVLRQV 2: OHW _3DUVH5HJH[_B_ UHJH[ VWU 3: PDWFK 5HJH[ 0DWFK VWU UHJH[ ZLWK 4: _ P ZKHQ QRW P 6XFFHVV ! 1RQH _ P ! >IRU [ LQ P *URXSV ! [ 9DOXH@ _! /LVW WDLO _! 6RPH 5: 6: OHW SDUVH'DWH VWU 7: PDWFK VWU ZLWK 8: _ 3DUVH5HJH[ # A ?G^ ` ?G^ ` ?G^ ` 9: >,QWHJHU P ,QWHJHU G ,QWHJHU \@ ! 6\VWHP 'DWH7LPH \ P G 10: _ 3DUVH5HJH[ # A ?G^ ` ?G^ ` ?G^ ` 11: >,QWHJHU P ,QWHJHU G ,QWHJHU \@ 12: ! 6\VWHP 'DWH7LPH \ P G 13: _ 3DUVH5HJH[ # A ?G^ ` ?G^ ` ?G^ ` >,QWHJHU \ ,QWHJHU P ,QWHJHU G@ 14: ! 6\VWHP 'DWH7LPH \ P G 15: _ B ! 6\VWHP 'DWH7LPH 16: 17: 18:
Generics F# generics are very similar to Scala, with a few diferences: Automatic Generalization If the function has no dependency on the specific type of a parameter, the type is inferred to be generic Statically Resolved Type Parameters Type parameter replaced with actual types at compile time instead of at run time No generics of generics Generics are native to .NET platform (no erasures) but on the other hand are more limited (no type classes)
1: $XWRPDWLF *HQHUDOL]DWLRQ 2: OHW _! [ I I [ 3: YDO _! [ D ! I D ! E ! E 4: &RQVWUDLQWV 5: OHW PD[ [ \ LI [ ! \ WKHQ [ HOVH \ 6: YDO PD[ [ D ! \ D ! D ZKHQ D FRPSDULVRQ 7: 8: 6\QWD[ IRU VWDWLFDOO\ UHVROYHG W\SH SDUDPHWHUV LV QRW EHDXWLIXO 9: DQG LW V PDLQO\ LQWHQWHG IRU FRUH OLEUDU\ IXQFWLRQV +RZHYHU LW FDQ EH XVHG ZLWK LQOLQH IXQFWLRQV IRU QHDW WULFNV OLNH GXFN W\SLQJ 10: OHW LQOLQH PDNH1RLVH DQLPDO AD ZKHQ AD PHPEHU 0DNH1RLVH XQLW !XQLW 11: AD PHPEHU 0DNH1RLVH XQLW !XQLW DQLPDO 12: 13: W\SH 'RJ PHPEHU BB 0DNH1RLVH SULQWIQ *XDX W\SH &DW PHPEHU BB 0DNH1RLVH SULQWIQ 0LDX 14: 15: PDNH1RLVH 'RJ 16: PDNH1RLVH &DW 17: 18: 19:
No generics of generics Type classes like Functor are not al owed 1: )XQFWRU PDS D ! E ! 7 D! ! 7 E! Instead, _map_ must be implemented for each type (or interface) 1: /LVW PDS D ! E ! OLVW D! ! OLVW E! 2: $UUD\ PDS D ! E ! DUUD\ D! ! DUUD\ E! 3: 6HT PDS D ! E ! VHT D! ! VHT E!
Collections F# built-in functions and operators and focus only on a few col ection types: Immutable? Feature Scala list Yes Linked list List seq Yes Lazy evaluation Iterable/Stream array No Random access Array map Yes Indexed access Map set Yes Unique items Set
F# Comprehensions F# al ows comprensions similar to those in Haskel or Python 1: OHW P\/LVW > IRU L LQ GR \LHOG L L @ 2: OHW P\$UUD\ >_ IRU L LQ ! L L _@ 3: OHW P\6HT VHT ^ IRU L LQ ! L L ` 4: C !C LV D VKRUWFXW IRU CGR \LHOGC 5: In Scala we would just use functions 1: /LVW UDQJH PDS L ! L L
Observables F# core library also includes support for Functional Reactive Programming 1: OHW PDNH6WUHDP LQWHUYDO 2: OHW W 6\VWHP 'DWH7LPH 1RZ 3: OHW WLPHU QHZ 6\VWHP 7LPHUV 7LPHU IORDW LQWHUYDO $XWR5HVHW WUXH 4: WLPHU 6WDUW WLPHU (ODSVHG 5: _! 2EVHUYDEOH PDS IXQ W ! LQWHUYDO W 6LJQDO7LPH W 6: 7: OHW VLPXOWDQHRXV6WUHDP QRQ6LPXOWDQHRXV6WUHDP 8: 2EVHUYDEOH PHUJH PDNH6WUHDP PDNH6WUHDP 9: _! 2EVHUYDEOH SDLUZLVH _! 2EVHUYDEOH SDUWLWLRQ IXQ B W B W ! 10: W W 7RWDO0LOOLVHFRQGV 11: 12: OHW IL]]6WUHDP EX]]6WUHDP 13: QRQ6LPXOWDQHRXV6WUHDP _! 2EVHUYDEOH PDS IXQ HY B ! HY 14: _! 2EVHUYDEOH SDUWLWLRQ IXQ LG B ! LG 15: 16: 17:
Scala Comprehensions and F# Computation Expressions In Scala, any type implementing filterWith, map and flatMap can be used with for comprehensions. This al ows, for example, dealing with async operations in a monadic way. 1: YDO XVG4XRWH )XWXUH ^ FRQQHFWLRQ JHW&XUUHQW9DOXH 86' ` 2: YDO FKI4XRWH )XWXUH ^ FRQQHFWLRQ JHW&XUUHQW9DOXH &+) ` 3: 4: YDO SXUFKDVH IRU ^ XVG XVG4XRWH 5: FKI FKI4XRWH 6: LI LV3URILWDEOH XVG FKI 7: ` \LHOG FRQQHFWLRQ EX\ DPRXQW FKI 8: 9: SXUFKDVH RQ6XFFHVV ^ FDVH B ! SULQWOQ 3XUFKDVHG DPRXQW &+) 10: ` 11: 12:
In F#, this can be done using computation expressions 1: 3DUDOOHO , 2 2: OHW IHWFK8UO$V\QF XUO DV\QF ^ 3: OHW UHT 6\VWHP 1HW :HE5HTXHVW &UHDWH 6\VWHP 8UL XUO 4: XVH UHVS UHT $V\QF*HW5HVSRQVH XVH VWUHDP UHVS *HW5HVSRQVH6WUHDP 5: XVH UHDGHU QHZ 6\VWHP ,2 6WUHDP5HDGHU VWUHDP 6: UHWXUQ UHDGHU 5HDG7R(QG 7: ` 8: 9: > KWWS IVKDUS RUJ KWWS ZZZ VFDOD ODQJ RUJ @ _! /LVW PDS IHWFK8UO$V\QF 10: _! $V\QF 3DUDOOHO 11: _! $V\QF 5XQ6\QFKURQRXVO\ 12: _! SULQWIQ $ 13: 14: Computation expressions convert language constructs like let, use, do, for or try in syntactic suga rfor continuation passing style operations
F# core has Asynchronous Workflows built-in 1: 3DUDOOHO &38 2: OHW UHF ILE [ 3: LI [ 4: WKHQ HOVH ILE [ ILE [ 5: 6: OHW ILEV 7: > IRU L LQ ! DV\QF ^ UHWXUQ ILE L ` @ 8: _! $V\QF 3DUDOOHO 9: _! $V\QF 5XQ6\QFKURQRXVO\ _! SULQWIQ $ 10: 11: Async<'T> is lazy, it wil only start running after cal ing Async.Start or Async.RunSynchronously
Custom computation expressions 1: W\SH 0D\EH%XLOGHU 2: PHPEHU BB %LQG [ I 2SWLRQ ELQG I [ 3: PHPEHU BB 5HWXUQ Y 6RPH Y 4: PHPEHU BB 5HWXUQ)URP R R OHW PD\EH 0D\EH%XLOGHU 5: 6: OHW ULVN\2S [ \ 7: LI [ \ WKHQ 6RPH [ \ HOVH 1RQH 8: 9: OHW H[HF0D\EH [ PD\EH ^ OHW D ULVN\2S [ [ 10: OHW E ULVN\2S D D 11: OHW F ULVN\2S E E 12: OHW G ULVN\2S F F 13: UHWXUQ G ` 14: H[HF0D\EH 15: 16: 17: Besides Bind and Return, there are other method s wich can be implemented by custom computations expressions like Zero, Yield, Combine, For, While or Try
Query expressions Query expressions provide support for LINQ in F# 1: TXHU\ ^ 2: IRU Q LQ GE 6WXGHQW GR 3: MRLQ H LQ GE &RXUVH6HOHFWLRQ RQ 4: Q 6WXGHQW,' H 6WXGHQW,' FRXQW 5: ` 6: They express transformations on a data source wich can be translated to another language, usual y SQL 1: 6(/(&7 &2817 )520 2: 6WXGHQW -2,1 &RXUVH6HOHFWLRQ 3: 21 6WXGHQW 6WXGHQW,' &RXUVH6HOHFWLRQ 6WXGHQW,'
And now for a couple of unique F# features...
Units of Measure 1: > 0HDVXUH!@ W\SH NP 'HILQH WKH PHDVXUH XQLWV 2: > 0HDVXUH!@ W\SH PL DV VLPSOH W\SHV GHFRUDWHG 3: > 0HDVXUH!@ W\SH K ZLWK 0HDVXUH DWWULEXWH 4: OHW VSHHG NP! K! &DQ EH FRPELQHG WKURXJK 5: OHW VSHHG PL! K! DULWKPHWLF RSHUDWLRQV 6: 7: OHW Y Y Y NP K! NP K! PL K! 8: OHW VXP Y Y 9: OHW VXP Y Y (UURU GRHVQ W FRPSLOH 10: &DQ EH XVHG LQ D JHQHULF ZD\ 11: W\SH 9HFWRU ' > 0HDVXUH!@ X! 12: ^ [ IORDW X! \ IORDW X! ] IORDW X! ` 13: 14: Measure annotations disappear after compilation and thus they have no performance penalty (Cannot be retrieved by Reflection though)