Learn You a Frege for Great Good!Pure functional programming language for JVM
CheshireCat (@y_taka_23)
Tokyo Kabukiza.tech Meetup #9 (2016/03/20)
Who am I?
● Name : CheshireCat○ Twitter: @y_taka_23
○ GitHub: y-taka-23
● Favorites○ Haskell
○ Formal methods (Coq, Alloy, SPIN etc...)
● (Would-be) Frege evangelist
Agenda
● What is Frege?○ Basic features
○ Compatibility with Haskell
● Frege as a JVM language○ How to deal the impurity
○ Java interoperation
Frege’s Essence
● Pure, non-strict functional language
● Strictly-typed, Hindley-Milner type inference
● Java interoperation with elegance
“Hello, World” in Haskell
module Hello where
greeting :: String -> Stringgreeting name = “Hello, ” ++ name
main :: IO ()main = do putStrLn $ greeting “World”
“Hello, World” in Frege
module Hello where
greeting :: String -> Stringgreeting name = “Hello, ” ++ name
main :: [String] -> IO ()main args = do putStrLn $ greeting “World”
“Learn you a Haskell” Translation
● All example snipets into Frege○ https://github.com/y-taka-23/learn-you-a-frege
● Compilable even in “dead-copied” translation
Compatibility with Haskell
● Syntax, standard libs : almost compatible!
● Hard to use in “practical” Haskell○ External dependencies
○ Most of GHC extensions
○ Template Haskell
● Java interoperation is necessary
Advantage of JVM Languages
● Platform-independent○ Frege compiler generates Java source codes
● Feel free to invoke Java libraries○ But pretty different regarding side-effects
■ Frege : Pure
■ Java : Impure, objects have own states
“Levels” of Java’s Impurity
● Immutable○ Maps to Frege’s data types directly
● Mutable, but without I/O○ ???
● With I/O○ ???
Immutable Classes
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
Immutable Classes
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
the identifier for Frege
Immutable Classes
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
“pure native”, if it’s immutable
Immutable Classes
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
the FQCN in Java
Immutable Classes
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
the constructor
Immutable Classes
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
BigInteger#add in Java
Immutable Classes
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
invoke the method by dot-notations
“Levels” of Java’s Impurity
● Immutable○ Maps to Frege’s data types directly
● Mutable, but without I/O○ ???
● With I/O○ Maps to IO monads
Classes with I/O
data JFReader = mutable native java.io.FileReader where native new :: String -> IO JFReader native read :: JFReader -> IO Int
readOneFrom :: String -> IO IntreadOneFrom filename = do fr <- JFReader.new filename fr.read
Classes with I/O
data JFReader = mutable native java.io.FileReader where native new :: String -> IO JFReader native read :: JFReader -> IO Int
readOneFrom :: String -> IO IntreadOneFrom filename = do fr <- JFReader.new filename fr.read
“mutable native”, if it acts on I/O
Classes with I/O
data JFReader = mutable native java.io.FileReader where native new :: String -> IO JFReader native read :: JFReader -> IO Int
readOneFrom :: String -> IO IntreadOneFrom filename = do fr <- JFReader.new filename fr.read
the return values are in IO contexts
Classes with I/O
data JFReader = mutable native java.io.FileReader where native new :: String -> IO JFReader native read :: JFReader -> IO Int
readOneFrom :: String -> IO IntreadOneFrom filename = do fr <- JFReader.new filename fr.read
use them as IO monads
“Levels” of Java’s Impurity
● Immutable○ Maps to Frege’s data types directly
● Mutable, but without I/O○ ???
● With I/O○ Maps to IO monads
“Outwardly Pure” Methods
public String greeting(String name) { StringBuilder sb = new StringBuilder(“Hello, ”); sb.append(name); return sb.toString();}
“Outwardly Pure” Methods
public String greeting(String name) { StringBuilder sb = new StringBuilder(“Hello, ”); sb.append(name); return sb.toString();}
mutation (i.e. destructive updating)
“Outwardly Pure” Methods
public String greeting(String name) { StringBuilder sb = new StringBuilder(“Hello, ”); sb.append(name); return sb.toString();}
but the return value is pure, though
“Levels” of Java’s Impurity
● Immutable○ Maps to Frege’s data types directly
● Mutable, but without I/O○ Maps to ST monads
● With I/O○ Maps to IO monads
ST (State Transformer) Monads
● Encapsulates destructive mutations
● ST s TypeName
○ s represents ”unobservable” internal states
○ s must be a type variable
● We can retrieve pure values from the contexts○ Unlike IO monads
Mutable Classes
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
Mutable Classes
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
“native”, if it has no I/O effects
Mutable Classes
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
“unobservable” states
Mutable Classes
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
wrap the values in “Mutable s”
Mutable Classes
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
the return values are in ST contexts
Mutable Classes
greeting :: String -> ST s Stringgreeting name = do sb <- JBuilder.new “Hello, ” sb.append name sb.toString
pureFunc :: String -> StringpureFunc name = (greeting name).run
Mutable Classes
greeting :: String -> ST s Stringgreeting name = do sb <- JBuilder.new “Hello, ” sb.append name sb.toString
pureFunc :: String -> StringpureFunc name = (greeting name).run
use them as ST monads
Mutable Classes
greeting :: String -> ST s Stringgreeting name = do sb <- JBuilder.new “Hello, ” sb.append name sb.toString
pureFunc :: String -> StringpureFunc name = (greeting name).run
“run” it to retrieve the pure value
Mutable Classes
greeting :: String -> ST s Stringgreeting name = do sb <- JBuilder.new “Hello, ” sb.append name sb.toString
pureFunc :: String -> StringpureFunc name = (greeting name).run
we can regard it as a pure function
Summary
● Frege is the very Haskell for JVM○ Syntax is just like Haskell’s
○ Pretty low learning cost for Haskellers
● Java interoperation with elegance○ Compatible with the Haskell-like type system
○ Classify side-effects into pure, ST and IO