Functional Programming and the Web Frontend Development in Purescript Michael Karg Jürgen Nicklisch-Franken
Hello! We are Symbolian ▣ Founded February 2015 in Berlin ▣ Currently 5 employees + external expertise ▣ Efficient software factory for high quality code ▣ Technology-driven innovation
1. Purescript The language
History and authors Phil Freeman Gary Burgess – Developer at SlamData John A. De Goes – CTO of SlamData In development since 2013, current version 0.8 (Feb. 2016) Notable companies: SlamData – Visual Analytics for NoSQL (Boulder, CO)
Project structure psc – purescript compiler psci – interactive REPL psc-bundle - “linker” / deployment tool psc-docs – documentation generator (markdown format) psc-publish – documentation generator for the pursuit API search engine psc-hierarchy – graphical doumentation generator for type classes Project language: Haskell psc target language: JavaScript
Language properties purely functional strong, static type system compiles to human-readable JavaScript standalone output – no dedicated JavaScript runtime necessary
Code generation examples i n c r e m e n t :; f o r a l l f . ( F u n c t o r f ) =? f I n t -? f I n t i n c r e m e n t = m a p ( + 1 ) v a r i n c r e m e n t = f u n c t i o n ( _ _ d i c t _ F u n c t o r _ 0 ) { r e t u r n P r e l u d e . m a p ( _ _ d i c t _ F u n c t o r _ 0 ) ( f u n c t i o n ( _ 0 ) { r e t u r n _ 0 + 1 | 0 ; } ) ; } ; m a i n = d o r e f <. n e w S T R e f " H e l l o " r e a d S T R e f r e f >>> l o g v a r m a i n = f u n c t i o n _ _ d o ( ) { v a r _ 1 = C o n t r o l _ M o n a d _ S T . n e w S T R e f ( " H e l l o " ) ( ) ; r e t u r n P r e l u d e [ " >>> " ] ( C o n t r o l _ M o n a d _ E f f . b i n d E f f ) ( C o n t r o l _ M o n a d _ S T . r e a d S T R e f ( _ 1 ) ) ( C o n t r o l _ M o n a d _ E f f _ C o n s o l e . l o g ) ( ) ; } ;
Language properties Purescript's design promises a smooth transition for developers from Haskell similar type class hierarchy ● c l a s s ( E q a ) < = O r d a w h e r e c o m p a r e :; a -? a -? O r d e r i n g similar abstractions and control structures (Monads / Effects, Applicatives, Functors, ...) ● similar syntax (pattern matching, do-notation, modules, sum and product data types, ● newtypes / type aliases, language keywords) similar type annotations ● l i f t M 1 :; f o r a l l m a b . ( M o n a d m ) =? ( a -? b ) -? m a -? m b l i f t M 1 f a = d o a ' <. a r e t u r n ( f a ' )
Differences from Haskell - Syntax no tuple syntax ● no cons patterns (less powerful pattern matching) ● row polymorphism in records ● l e t s h o w P e r s o n { f i r s t : x , l a s t : y } = y +, " , " +, x l e t p e r s o n 1 = { f i r s t : " P h i l " , l a s t : " F r e e m a n " } s h o w P e r s o n p e r s o n 1 " F r e e m a n , P h i l " s h o w P e r s o n { f i r s t : " P h i l " , l a s t : " F r e e m a n " , l o c a t i o n : " L o s A n g e l e s " } " F r e e m a n , P h i l " record access ● p e r s o n 1 . l a s t
Differences from Haskell – Types Explicit f ● o r a l l Named instances ● Extensible Effects ● m a i n :; f o r a l l e f f . -? E f f ( c a n v a s :; C a n v a s , , r a n d o m :; R A N D O M , e r r :; E X C E P T I O N , s t :; S T C o n e S T , d o m :; D O M | e f f ) U n i t
Differences from Haskell – The JS world evaluated by a JavaScript engine (V8, Spidermonkey...) ● ==> strict evaluation; no concurrency; varying performance characteristics package splits are cheap ● ==> minimal Prelude (~ 730 sloc), highly specialized packages (purescript-either, purescript- maybe, ...) FFI into the JS world ● f o r e i g n i m p o r t c o n c a t S t r i n g :; S t r i n g -? S t r i n g -? S t r i n g e x p o r t s . c o n c a t S t r i n g = f u n c t i o n ( s 1 ) { r e t u r n f u n c t i o n ( s 2 ) { r e t u r n s 1 + s 2 ; } ; } ;
2. Purescript The ecosystem
Basics: building psc + node / npm, bower – well-known tools of the JS world pulp build system ==> no difficulties for any frontend developer However: very little compiler optimizations (only TCO and DCE) ==> without inlining and partial vs. total application in function calls, the equivalent plain JS code performs notably better
Search: pursuit -- https://pursuit.purescript.org Search by symbol name, type or package name (just like hoogle or hayoo)
Framework: Thermite wrapper for ReactJS with a clean functional API
Framework: Halogen t y p e S t a t e = { c o u n t :; I n t } a type-safe declarative UI d a t a I n p u t a library = I n c r e m e n t a | D e c r e m e n t a native Purescript implementation u i :; f o r a l l g . ( F u n c t o r g ) =? C o m p o n e n t S t a t e I n p u t g u i = c o m p o n e n t r e n d e r e v a l w h e r e r e n d e r s t a t e = H . d i v _ [ H . b u t t o n [ E . o n C l i c k $ E . i n p u t _ D e c r e m e n t ] [ H . t e x t " - " ] , H . p _ [ H . t e x t ( s h o w s t a t e . c o u n t ) ] , H . b u t t o n [ E . o n C l i c k $ E . i n p u t _ I n c r e m e n t ] [ H . t e x t " + " ] ] ● e v a l :; E v a l I n p u t S t a t e I n p u t g e v a l ( I n c r e m e n t n e x t ) = d o m o d i f y ( \ s t a t e -? s t a t e { c o u n t = s t a t e . c o u n t + 1 } ) p u r e n e x t e v a l ( D e c r e m e n t n e x t ) = d o m o d i f y ( \ s t a t e -? s t a t e { c o u n t = s t a t e . c o u n t - 1 } ) p u r e n e x t
Graphics: LambdaCube 3D purely functional DSL for programming the GPU WebGL rendering backend uses Purescript
Conclusion wide and diverse ecosystem for such a relatively young language fast-growing toolbox for tackling your individual use case plenty of interesting approaches and projects to toy around with and get fresh ideas
3. Purescript The community
Why community? Community: Populace of any language's ecosystem Community size and structure directly influences the way a language is being used, and can be used When choosing a language for commercial development and productive use: get to know the community as well Given the demands of a commercial application of any language: will its community be a support, or an obstacle? NB. No intention to judge people; just one adaptation more of your development process, trying to avoid false expectations
The purescript community purescript compiler: 4 individuals ~ 2/3 of all commits same individuals responsible for the vast majority of purescript packages ==> tiny community
The purescript community tight-knit communication communication often in closed circles or one on one compared to the Haskell community, seldom open debates or call for feedback discussions take place in github's issue tracker or the purescript IRC channel – not the best way to keep up or retrace consequence: hasty and premature decisions, lack of prioritization of open issues and TODOs
Examples explicit imports – implement, protest, rethink, shrug removal of cons patterns... in a language boasting pattern matching restructuring of type class hierarchy; (cf. Int / Num) NB. w/o inliner, each (+), (-), ... still corresponds to a dictionary lookup of the instance's method at runtime, impacting performance orphan instances banned completely API changes in and refactoring of the Prelude ==> we're not talking about language periphery here ==> additionally, all of the above changes in no more than 6 months
The Ugly frequent breakage of your code base extra expenditure of time (> 1d) just to get it to build again due to the character of the community, changes may be pleasing from an aesthetical-theoretical POV, but real world code becomes horrible
Recommend
More recommend