Successfully reported this slideshow.
Upcoming SlideShare
×

# Commercial Uses of Functional Programming

16,116 views

Published on

FLOLAC'14 talk on using Haskell in commercial settings.

Published in: Technology
• Full Name
Comment goes here.

Are you sure you want to Yes No

### Commercial Uses of Functional Programming

1. 1. 2014-07-01 FLOLAC’14 Commercial Uses of Functional Programming Functional Programming as a means — not an end
2. 2. 01
3. 3. 01 ✤ ICFP 2014: September 1~3
4. 4. 01 ✤ ICFP 2014: September 1~3 ✤ CUFP 2014: September 4~6
5. 5. 01 ✤ ICFP 2014: September 1~3 ✤ CUFP 2014: September 4~6 ✤ 6-Hour Workday: July 1
6. 6. 01 ✤ ICFP 2014: September 1~3 ✤ CUFP 2014: September 4~6 ✤ 6-Hour Workday: July 1
7. 7. 01
8. 8. 01
9. 9. 01 Worse is Better
10. 10. 01 Worse is Better
11. 11. 01 Worse is Better Less is More!
12. 12. Less is more! λ Closure ⊂ Value
13. 13. Less is more! λ Closure ⊂ Value f . g =
14. 14. Less is more! λ Closure ⊂ Value f . g = x -> f (g x)
15. 15. Less is more! λ Closure ⊂ Value f . g = x -> f (g x) ((+1) . (*2)) 3
16. 16. Less is more! λ Closure ⊂ Value function compose (f, g) { return function (x) { return f( g(x) ) } } f . g = x -> f (g x) ((+1) . (*2)) 3
17. 17. ANSI C Ada Fortran Cobol
18. 18. ANSI C Ada Fortran Cobol
19. 19. ANSI C Ada Fortran Cobol
20. 20. ANSI C Ada Fortran Cobol
21. 21. ANSI C Ada Fortran Cobol
22. 22. ANSI C Ada Fortran Cobol
23. 23. ANSI C Ada Fortran Cobol
24. 24. ANSI C Ada Fortran Cobol
25. 25. ANSI C Ada Fortran Cobol
26. 26. ANSI C Ada Fortran Cobol
27. 27. ANSI C Ada Fortran Cobol
28. 28. ANSI C Ada Fortran Cobol
29. 29. ANSI C Ada Fortran Cobol
30. 30. Generators: List Fusion
31. 31. Generators: List Fusion fibs = 1:1:[ x+y  | x <- fibs  | y <- tail fibs ] take 6 (map (*10) fibs) [10,10,20,30,50,80]
32. 32. Generators: List Fusion fibs = 1:1:[ x+y  | x <- fibs  | y <- tail fibs ] take 6 (map (*10) fibs) [10,10,20,30,50,80] take 6 (map (*5) (map (*2) fibs)) [10,10,20,30,50,80]
33. 33. Generators: List Fusion fibs = 1:1:[ x+y  | x <- fibs  | y <- tail fibs ] take 6 (map (*10) fibs) [10,10,20,30,50,80] take 6 (map (*5) (map (*2) fibs)) [10,10,20,30,50,80] take 6 (map ((*5) . (*2)) fibs)
34. 34. QuickCheck: PropertyTesting
35. 35. QuickCheck: PropertyTesting import Test.QuickCheck prop :: [Int] -> [Int] -> Bool prop xs ys = reverse (xs ++ ys) == reverse xs ++ reverse ys quickCheck prop -- Failed!
36. 36. QuickCheck: PropertyTesting import Test.QuickCheck prop :: [Int] -> [Int] -> Bool prop xs ys = reverse (xs ++ ys) == reverse xs ++ reverse ys quickCheck prop -- Failed! reverse xs ++ reverse ys
37. 37. QuickCheck: PropertyTesting import Test.QuickCheck prop :: [Int] -> [Int] -> Bool prop xs ys = reverse (xs ++ ys) == reverse xs ++ reverse ys quickCheck prop -- Failed! reverse xs ++ reverse ys quickCheck prop -- Failed!
38. 38. QuickCheck: PropertyTesting import Test.QuickCheck prop :: [Int] -> [Int] -> Bool prop xs ys = reverse (xs ++ ys) == reverse xs ++ reverse ys quickCheck prop -- Failed! reverse ys ++ reverse xs quickCheck prop -- Passed!
39. 39. Macros: Multi-Stage Programming
40. 40. Macros: Multi-Stage Programming import Text.InterpolatedString.Perl6 user = "world" putStrLn [qq| Hello, \$user! Your lucky number: { 6*7 } |]
41. 41. 2011 20142004
42. 42. 2011 20142004 2005
43. 43. 2011 20142004 2005 2012
44. 44. ES/9000 R46 4CPU, 8GB RAM 50MTWD
45. 45. RS/6000 H70 340MHz 1MTWD ES/9000 R46 4CPU, 8GB RAM 50MTWD
46. 46. InfoPrint/4000 ID5 1000 PPM 15MTWD RS/6000 H70 340MHz 1MTWD ES/9000 R46 4CPU, 8GB RAM 50MTWD
47. 47. InfoPrint/4000 ID5 1000 PPM 15MTWD RS/6000 H70 340MHz 1MTWD ES/9000 R46 4CPU, 8GB RAM 50MTWD
48. 48. InfoPrint/4000 ID5 1000 PPM 15MTWD RS/6000 H70 340MHz 1MTWD ES/9000 R46 4CPU, 8GB RAM 50MTWD COBOL RPG PL/1 REXX SQL
49. 49. InfoPrint/4000 ID5 1000 PPM 15MTWD RS/6000 H70 340MHz 1MTWD ES/9000 R46 4CPU, 8GB RAM 50MTWD COBOL RPG PL/1 REXX SQL
50. 50. Content Manager OnDemand Feb 2004
51. 51. Content Manager OnDemand Feb 2004
52. 52. Content Manager OnDemand Encode::IBM Parse::AFP Feb 2004
53. 53. Content Manager OnDemand Encode::IBM Parse::AFP Feb 2004
54. 54. Content Manager OnDemand  Encode::IBM Parse::AFP Feb 2004
55. 55. September 2004
56. 56. September 2004
57. 57. September 2004
58. 58.   September 2004
59. 59.   September 2004 SAX-style iterators
60. 60.   September 2004 SAX-style iterators O(n) memory use
61. 61.   September 2004 SAX-style iterators O(n) memory use 300KB/sec (my laptop)
62. 62.   September 2004 SAX-style iterators O(n) memory use 300KB/sec (my laptop) 30KB/sec (production)
63. 63.   September 2004 SAX-style iterators O(n) memory use 300KB/sec (my laptop) 30KB/sec (production) Input: 25GB/day Throughput: 2.5GB/day
64. 64.   September 2004 SAX-style iterators O(n) memory use 300KB/sec (my laptop) 30KB/sec (production) Input: 25GB/day Throughput: 2.5GB/day Deadline: Feb 2005
65. 65. October—November 2004
66. 66. October—November 2004
67. 67. October—November 2004
68. 68. December 2004: Freenode
69. 69. December 2004: Freenode ✤ “Yeah, CosmicRay recently ported GHC to AIX.”
70. 70. December 2004: Freenode ✤ “Yeah, CosmicRay recently ported GHC to AIX.” ✤ “Deﬁning a functor instance as liftM works I'm pretty sure, so… all Monads are Functors (theoretically), instance Monad a => Functor a where fmap = liftM would cover all monads.”
71. 71. December 2004: Freenode ✤ “Yeah, CosmicRay recently ported GHC to AIX.” ✤ “Deﬁning a functor instance as liftM works I'm pretty sure, so… all Monads are Functors (theoretically), instance Monad a => Functor a where fmap = liftM would cover all monads.” ✤ “Elaborate please? <- have only learned haskell for 5 days…”
72. 72. December 2004: Freenode ✤ “Yeah, CosmicRay recently ported GHC to AIX.” ✤ “Deﬁning a functor instance as liftM works I'm pretty sure, so… all Monads are Functors (theoretically), instance Monad a => Functor a where fmap = liftM would cover all monads.” ✤ “Elaborate please? <- have only learned haskell for 5 days…” ✤ “unsafeInterleaveIO is the best thing since sliced bread.”
73. 73. December 2004: Freenode ✤ “Yeah, CosmicRay recently ported GHC to AIX.” ✤ “Deﬁning a functor instance as liftM works I'm pretty sure, so… all Monads are Functors (theoretically), instance Monad a => Functor a where fmap = liftM would cover all monads.” ✤ “Elaborate please? <- have only learned haskell for 5 days…” ✤ “unsafeInterleaveIO is the best thing since sliced bread.” ✤ “What do I do with a compiler with exploding brains?”
74. 74. December 2004: Freenode ✤ “Yeah, CosmicRay recently ported GHC to AIX.” ✤ “Deﬁning a functor instance as liftM works I'm pretty sure, so… all Monads are Functors (theoretically), instance Monad a => Functor a where fmap = liftM would cover all monads.” ✤ “Elaborate please? <- have only learned haskell for 5 days…” ✤ “unsafeInterleaveIO is the best thing since sliced bread.” ✤ “What do I do with a compiler with exploding brains?” ✤ “Haskell has a solid niche as a PhD generator :)”
75. 75. January 2005
76. 76. January 2005 ✤ OpenAFP.hs delivered —
77. 77. Input: 25GB/day Throughput: 500GB/day DOM-Style selectors O(1) Memory Use! January 2005 ✤ OpenAFP.hs delivered —
78. 78. Input: 25GB/day Throughput: 500GB/day DOM-Style selectors O(1) Memory Use! January 2005 ✤ OpenAFP.hs delivered — ✤ NTD\$3k/hr * 3 months
79. 79. Input: 25GB/day Throughput: 500GB/day DOM-Style selectors O(1) Memory Use! January 2005 ✤ OpenAFP.hs delivered — ✤ NTD\$3k/hr * 3 months ✤ “You don't need category theory, you need BC Pierce's 'Types and Programming Languages’”
80. 80. Input: 25GB/day Throughput: 500GB/day DOM-Style selectors O(1) Memory Use! January 2005 ✤ OpenAFP.hs delivered — ✤ NTD\$3k/hr * 3 months ✤ “You don't need category theory, you need BC Pierce's 'Types and Programming Languages’”
81. 81. Input: 25GB/day Throughput: 500GB/day DOM-Style selectors O(1) Memory Use! January 2005 ✤ OpenAFP.hs delivered — ✤ NTD\$3k/hr * 3 months ✤ “You don't need category theory, you need BC Pierce's 'Types and Programming Languages’”      ✤ “My target language is huge. I need all the help I can get :)”
82. 82. 2005: Pugs Feb 1: Started on Freenode #haskell Lambdas & Camels joined in #perl6 Speciﬁcation revised, iterated, tested Concurrency, Coroutines, Commit Bits!
83. 83. 2006: Erdősing YAPC: Worst is Best on targeting JS OOPSLA: Reconciling the Irreconcilable Succeeded by Moose & Rakudo Perl 5 runtime became Modern Perl Concluding talk: Optimizing for Fun 楽 ⼟土
84. 84. 2007: S-Team New tech stack: Jifty, Moose, and GHC OpenAFP Utilities: Report Generation, Extraction, Management, Distribution, Conversion… Enhanced & eventually replaced IBM OnDemand with PDF-based workﬂow
85. 85. 2008: Socialtext Midlife crisis — Becoming a PHB? Hierarchical organization & culture — can we change that with technology? Decided to telecommute full time:  - ST (social workplace), or  - FB (social media)?
86. 86. 2009: SocialCalc Worked with Dan Bricklin & friends Summarized into three book chapters:  - Architecture of Open Source Applications  - Performance of Open Source Applications  - 500 lines or less (in progress) EtherCalc: Backend of g0v.today
87. 87. 2010:Apple Cloud Service Localization Everything under NDA… …with one single exception
88. 88. May 2011
89. 89. May 2011 ✤ “Can you write me some code that takes a regular expression and enumerates the domain it accepts?”
90. 90. May 2011 ✤ “Can you write me some code that takes a regular expression and enumerates the domain it accepts?” ✤ “I think I can do this with the yices2 SMT solver and the SBV Haskell library to turn regexes into satisﬁability problems, and so we can get all examples.
91. 91. May 2011 ✤ “Can you write me some code that takes a regular expression and enumerates the domain it accepts?” ✤ “I think I can do this with the yices2 SMT solver and the SBV Haskell library to turn regexes into satisﬁability problems, and so we can get all examples. ✤ But this is too much fun for an one-off script…  Would you mind if I do this pro bono so I can release it into public domain? :-)”
92. 92. SMT Constraint Solving
93. 93. SMT Constraint Solving ✤ Genex: Regex as predicates on integer variables /([AB]C)1/
94. 94. SMT Constraint Solving ✤ Genex: Regex as predicates on integer variables ✤ Solve for [x, y, z, w]: /([AB]C)1/ (x=‘A’ ∨ x=‘B’) ∧ (y=‘C’) ∧ (z=x) ∧ (w=y)
95. 95. SMT Constraint Solving ✤ Genex: Regex as predicates on integer variables ✤ Solve for [x, y, z, w]: ✤ “ACAC”  “BCBC” /([AB]C)1/ (x=‘A’ ∨ x=‘B’) ∧ (y=‘C’) ∧ (z=x) ∧ (w=y)
96. 96. SMT Constraint Solving ✤ Genex: Regex as predicates on integer variables ✤ Solve for [x, y, z, w]: ✤ “ACAC”  “BCBC” ✤ Supports b 1 ^ \$ /([AB]C)1/ (x=‘A’ ∨ x=‘B’) ∧ (y=‘C’) ∧ (z=x) ∧ (w=y)
97. 97. A Regular Crossword (ND|ET|IN)[^X]* (DI|NS|TH|OM)* .*(IN|SE|HI) [CHMNOR]*I[CHMNOR]* C*MC(CCC|MM)* ([^EMC]|EM)* [CEIMU]*OH[AEMOR]* [AM]*CM(RC)*R? N.*X.X.X.*E .*XHCR.*X.* (RR|HHH)*.? (...?)1* .*XEXM* [CR]* [^C]*MMM[^C]* (E|CR|MN)* ([^X]|XCC)* .*OXR.* .*PRR.*DDC.* R*D*M* .*(.)(.)(.)(.)4321.* (RX|[^R])* .*SE.*UE.* .*LR.*RL.* (S|MM|HHH)* .*G.*V.*H.* [^C]*[^R]*III.* (HHX|[^HX])* .(C|HH)* .*DD.*CCM.* P+(..)1.* (O|RHH|MM)* ([^MC]|MM|CC)* .*(.)C1X1.* F.*[AO].*[AO].* [^M]*M[^M]* .*H.*H.* .* .*
98. 98. A Regular Crossword ✤ Source: MIT Mystery Hunt 2013 (ND|ET|IN)[^X]* (DI|NS|TH|OM)* .*(IN|SE|HI) [CHMNOR]*I[CHMNOR]* C*MC(CCC|MM)* ([^EMC]|EM)* [CEIMU]*OH[AEMOR]* [AM]*CM(RC)*R? N.*X.X.X.*E .*XHCR.*X.* (RR|HHH)*.? (...?)1* .*XEXM* [CR]* [^C]*MMM[^C]* (E|CR|MN)* ([^X]|XCC)* .*OXR.* .*PRR.*DDC.* R*D*M* .*(.)(.)(.)(.)4321.* (RX|[^R])* .*SE.*UE.* .*LR.*RL.* (S|MM|HHH)* .*G.*V.*H.* [^C]*[^R]*III.* (HHX|[^HX])* .(C|HH)* .*DD.*CCM.* P+(..)1.* (O|RHH|MM)* ([^MC]|MM|CC)* .*(.)C1X1.* F.*[AO].*[AO].* [^M]*M[^M]* .*H.*H.* .* .*
99. 99. A Regular Crossword ✤ Source: MIT Mystery Hunt 2013 ✤ Solved in ~40 lines of Haskell with Genex!(ND|ET|IN)[^X]* (DI|NS|TH|OM)* .*(IN|SE|HI) [CHMNOR]*I[CHMNOR]* C*MC(CCC|MM)* ([^EMC]|EM)* [CEIMU]*OH[AEMOR]* [AM]*CM(RC)*R? N.*X.X.X.*E .*XHCR.*X.* (RR|HHH)*.? (...?)1* .*XEXM* [CR]* [^C]*MMM[^C]* (E|CR|MN)* ([^X]|XCC)* .*OXR.* .*PRR.*DDC.* R*D*M* .*(.)(.)(.)(.)4321.* (RX|[^R])* .*SE.*UE.* .*LR.*RL.* (S|MM|HHH)* .*G.*V.*H.* [^C]*[^R]*III.* (HHX|[^HX])* .(C|HH)* .*DD.*CCM.* P+(..)1.* (O|RHH|MM)* ([^MC]|MM|CC)* .*(.)C1X1.* F.*[AO].*[AO].* [^M]*M[^M]* .*H.*H.* .* .*
100. 100. A Regular Crossword ✤ Source: MIT Mystery Hunt 2013 ✤ Solved in ~40 lines of Haskell with Genex!(ND|ET|IN)[^X]* (DI|NS|TH|OM)* .*(IN|SE|HI) [CHMNOR]*I[CHMNOR]* C*MC(CCC|MM)* ([^EMC]|EM)* [CEIMU]*OH[AEMOR]* [AM]*CM(RC)*R? N.*X.X.X.*E .*XHCR.*X.* (RR|HHH)*.? (...?)1* .*XEXM* [CR]* [^C]*MMM[^C]* (E|CR|MN)* ([^X]|XCC)* .*OXR.* .*PRR.*DDC.* R*D*M* .*(.)(.)(.)(.)4321.* (RX|[^R])* .*SE.*UE.* .*LR.*RL.* (S|MM|HHH)* .*G.*V.*H.* [^C]*[^R]*III.* (HHX|[^HX])* .(C|HH)* .*DD.*CCM.* P+(..)1.* (O|RHH|MM)* ([^MC]|MM|CC)* .*(.)C1X1.* F.*[AO].*[AO].* [^M]*M[^M]* .*H.*H.* .* .* N H P E H A S D I O M O M T H F O X N X A X P H M M O M M M M R H H M C X N M M C R X E M C M C C C C M M M M M M H R X R C M I I I H X L S O R E O R E O R E O R E V C X C C H H M X C C R R R R H H H R R U N C X D X E X L E R R D D M M M M G C C H H C C
101. 101. SmallCheck: Enumerated Series
102. 102. SmallCheck: Enumerated Series ✤ Type-Level Literals: Numbers and Symbols            xs :: [Matching "a?b?c?"] xs = list 100 series [,a,b,ab,c,ac,bc,abc]
103. 103. SmallCheck: Enumerated Series ✤ Type-Level Literals: Numbers and Symbols            ✤ Check properties for all strings matching a regex xs :: [Matching "a?b?c?"] xs = list 100 series [,a,b,ab,c,ac,bc,abc]
104. 104. QuickCheck: Random Sampling
105. 105. QuickCheck: Random Sampling ✤ Regular Expressions and XML Schemata: generate (matching rfc2822) "9%az4@rar1do04jkd1.agzy.org"
106. 106. QuickCheck: Random Sampling ✤ Regular Expressions and XML Schemata: generate (matching rfc2822) "9%az4@rar1do04jkd1.agzy.org" putStr . showXmlTree =<<  generate . matchingRNG =<<  loadRNG “book.rng” <?xml version="1.0" encoding="UTF-8"?><book> <author>o09a-_6w@tnj.qom.today</author> <author>3qd9g02xlu@swbr.kmly.eu</author> <author>z6ckxi8@jtm.cbopios.asia</author> </book>
107. 107. 2012: LiveScript Feb 1: @gkz forked @satyr’s fork of .coffee “Like a smaller language within Perl 6, struggling to get out…” May 1: ST joined PeopleFluent at Bedford June 1: CoffeeRedux by @michaelﬁcarra Launched JS2LS: @clkao, @gkz, @mpgutta Coco
108. 108. 2013: MoeDict Feb 1: Revised MoE Dictionary in HTML5 - Every word linked to its deﬁnition - Fair Use and CC0 as legal frameworks moedict.tw: Android, iOS, Firefox OS Holo, Hakka, Cross-Strait Language DB 萌典
109. 109. May 2014: CUFP Program Committee
110. 110. May 2014: CUFP Program Committee ✤ “I enjoyed @simonmar's slides The Haxl Project at Facebook and the related /r/haskell discussions.
111. 111. May 2014: CUFP Program Committee ✤ “I enjoyed @simonmar's slides The Haxl Project at Facebook and the related /r/haskell discussions. ✤ It’s a reasonably easy-to-understand Commercial Use of Functional Programming that I plan to talk about in my FLOLAC’14 talk.
112. 112. May 2014: CUFP Program Committee ✤ “I enjoyed @simonmar's slides The Haxl Project at Facebook and the related /r/haskell discussions. ✤ It’s a reasonably easy-to-understand Commercial Use of Functional Programming that I plan to talk about in my FLOLAC’14 talk. ✤ Would it make sense to invite @simonmar to the CUFP keynote?”
113. 113. Fighting Spam with Pure Functions
114. 114. Fighting Spam with Pure Functions ✤ Nov 2012: Simon Marlow joins Facebook
115. 115. Fighting Spam with Pure Functions ✤ Nov 2012: Simon Marlow joins Facebook ✤ Jan 2013: FXL — Subset of ML, interpreted in C++
116. 116. Fighting Spam with Pure Functions ✤ Nov 2012: Simon Marlow joins Facebook ✤ Jan 2013: FXL — Subset of ML, interpreted in C++ If (Average(Map(Reputation,   PreviousSharedUrls(User, 5))) < 0) Then [WarnUser, LogRequest] Else []
117. 117. Fighting Spam with Pure Functions ✤ Nov 2012: Simon Marlow joins Facebook ✤ Jan 2013: FXL — Subset of ML, interpreted in C++ ✤ Aug 2013: Haxl compiler implemented in GHC
118. 118. Fighting Spam with Pure Functions ✤ Nov 2012: Simon Marlow joins Facebook ✤ Jan 2013: FXL — Subset of ML, interpreted in C++ ✤ Aug 2013: Haxl compiler implemented in GHC ✤ Jun 2014: Deployed and Open Sourced
119. 119. Fighting Spam with Pure Functions ✤ Nov 2012: Simon Marlow joins Facebook ✤ Jan 2013: FXL — Subset of ML, interpreted in C++ ✤ Aug 2013: Haxl compiler implemented in GHC ✤ Jun 2014: Deployed and Open Sourced ✤ Sep 2014: There is no fork @ ICFP
120. 120. FXL on Haxl If (Average(Map(Reputation,   PreviousSharedUrls(User, 5))) < 0) Then [WarnUser, LogRequest] Else []
121. 121. FXL on Haxl If (Average(Map(Reputation,   PreviousSharedUrls(User, 5))) < 0) Then [WarnUser, LogRequest] Else []
122. 122. FXL on Haxl If (Average(Map(Reputation,   PreviousSharedUrls(User, 5))) < 0) Then [WarnUser, LogRequest] Else [] Marlow et al, The Haxl Project at Facebook
123. 123. FXL on Haxl If (Average(Map(Reputation,   PreviousSharedUrls(User, 5))) < 0) Then [WarnUser, LogRequest] Else [] Marlow et al, The Haxl Project at Facebook
124. 124. Concurrency & Caching
125. 125. Concurrency & Caching ✤ With the Applicative Do macro: fun :: Haxl String fun = [ado| x <- fetch “A” y <- fetch “B” z <- fetch y x ++ y ++ z |]
126. 126. Concurrency & Caching ✤ With the Applicative Do macro: fun :: Haxl String fun = [ado| x <- fetch “A” y <- fetch “B” z <- fetch y x ++ y ++ z |] fetch “A” fetch “B”
127. 127. Concurrency & Caching ✤ With the Applicative Do macro: fun :: Haxl String fun = [ado| x <- fetch “A” y <- fetch “B” z <- fetch y x ++ y ++ z |] fetch “A” fetch “B” H A
128. 128. Concurrency & Caching ✤ With the Applicative Do macro: fun :: Haxl String fun = [ado| x <- fetch “A” y <- fetch “B” z <- fetch y x ++ y ++ z |] fetch “A” fetch “B” H A fetch “A” H cached
129. 129. Concurrency & Caching ✤ With the Applicative Do macro: fun :: Haxl String fun = [ado| x <- fetch “A” y <- fetch “B” z <- fetch y x ++ y ++ z |] fetch “A” fetch “B” H A++ fetch “A” H cached ++ HAH
130. 130. Recap
131. 131. Recap ✤ Generators: List Fusion
132. 132. Recap ✤ Generators: List Fusion  ✤ QuickCheck: Property Testing
133. 133. Recap ✤ Generators: List Fusion  ✤ QuickCheck: Property Testing  ✤ Macros: Multi-Stage Programming
134. 134. main :: IO () Functional Programming as a means —
135. 135. main :: IO a Functional Programming as a means —
136. 136. main :: IO a Functional Programming as a means — newtype IO a = IO ( State# RealWorld -> (# State# RealWorld, a #))
137. 137. main :: IO a Functional Programming as a means — newtype IO a = IO ( State# RealWorld -> (# State# RealWorld, a #)) main :: State# RealWorld -> (# State# RealWorld, a #)
138. 138. main :: IO a Functional Programming as a means — newtype IO a = IO ( State# RealWorld -> (# State# RealWorld, a #)) main :: State# RealWorld -> (# State# RealWorld, a #) to observe the world,
139. 139. main :: IO a Functional Programming as a means — newtype IO a = IO ( State# RealWorld -> (# State# RealWorld, a #)) main :: State# RealWorld -> (# State# RealWorld, a #) to observe the world, to change it, and to create a new value.