Post on 22-Jan-2018
Frege: Design & Implementation
A short Overview
Ingo WechsungIT Consultant, contexo GmbH
Reutlingen, Germany
History
• Frege1
• Frege2
• Frege3
see http://www.infoq.com/news/2015/08/frege-haskell-for-jvm
Design Goals
• pure functional, statically typed, non-strict– essentially Haskell 2010
– plus higher ranked types
– more GHC features to be implemented on top
• easy integration in JVM ecosystem– a practical JVM language
– a (more funny) way to write (better) Java code
– be as familiar as possible for JVM programmers
Principles for Design Decisions
• when in doubt, do it like Haskell 2010– unless it makes no sense in JVM
• module system, FFI, exceptions, C-ish/POSIX-ish APIs
– unless outdated (Functor/Applicative/Monad)– maybe a bit simpler in certain cases– subsetting (e.g. standard/prelude libraries)
• add nice JVM stuff– regexes out of the box– long, java.lang.String– types as name spaces (makes records possible)
To err is human …
• class/instance syntax:class Eq a => Ord a / instance Eq a => Eq (Maybe a)
class Ord Eq a => a / instance Eq Eq a => Maybe a
thought it would be easier to parse, read and understand, but really is major annoyance.
• Java comment syntax, package/module
• Underestimation of how important source code compatibility would be.
Unintended Consequences
• for interoperability and speed: support and use primitive JVM types, hence
data Bool = pure native boolean
• requires literals
– familiarity concerns suggest true, false
• Haskell users [Confused .. Annoyed]
• Yet can‘t fix this easily without „cheating“ in the compiler.
Native Interface (aka FFI)
• not only functions, but also data types• JVM types appear as abstract data types
– need functions (i.e. JVM methods) too– (watch out: ADT abbreviates abstract as well as
algebraic data types.)– primitives, interfaces, classes, arrays– almost no knowledge about „basic types“ hardwired
in the compiler: it‘s all in the Prelude
• Haskell FFI not fit for JVM, replaced with NI– code that uses C functions is not portable anyway
Runtime Concerns
• provide Java methods where • synchronized { … }
• try { … } catch … finally { … }
would be needed.
• interfaces and classes for representation of
Frege ADT and functions
• thunks & lazy evaluation
Runtime System Overview (to be changed soon)
interface Applicable
interface Value
abstract Algebraic
abstract Lambda
abstract Delayed
function types
algebraic data types
interface Lazy
Created by applied
functions
Current vs. Upcoming Function Handling
● A FunN, when applied, creates a FunN-1, and Fun1 a Delayed.
● designed to minimize class files, because it covers partial applications.
● Create FunN “function pointers” for functions as needed.
● Re-use function pointers across modules.
● Higher order functions do not care about type/arity of passed functions.
● no partial application implemented in Java anymore
● thunks/lazy values are Callable<X>
● higher order functions expect functional arguments with exact arity
● should reduce number of intermediate instances drastically
● will create less class files in Java 8, more in Java 7
● more type safe calling from Java into Frege
Example
map (1+) list
map ((+) 1) list
List.map(plus123.apply(1),list)
…
Fun2 plus123 = new Fun2() {public Integer eval(Object a1,
Object a2) {return Delayed.<Integer>forced(a1) +
Delayed.<Integer>forced(a2); }}
map (1+) list
map (\x -> 1+x) list
List.map((Func1)(x -> 1 +
Thunk.<Integer>forced(x)), list)
Encoding of Product Types
data P a b = C a b
data R = Pair { !a, !b :: Int }
final class TP {final Object m1;final Object m2;
TP(Object a, Object b) {m1 = a; m2 = b;
}}
final class TR {final int mema, memb;…
}
Encoding of Sum Types
data S a b = S1 a | S2 b interface TS {
static class DS1 implements TS { DS1 _S1() { return this; }DS2 _S2() { return null; }…
}static class DS2 implements TS
{ … }
public DS1 _S1();public DS2 _S2();
}
See the REPL!
● There are no secrets in Frege.
● Just type an example in the REPL and use :java
command!
● Caveat: REPL tells you only how things are today.
● JVM evolution may offer opportunities we cannot
refuse.○ JVM8: lambdas
○ JVM?: value types
Three classes of values
● Immutable ○ All Frege types and pure native types
○ can be used everywhere
● Mutable only○ JVM types defined mutable native
○ native functions that use them must be IO actions
● Mutable○ JVM types defined native
○ can appear in ST actions or pure functions
Marshalling in the NI
● no arguments for static method: () -> ST s R
● nullable arguments of type X:
Maybe X or Maybe (Mutable s X)
● void method: ST s () or IO ()
● let return type be X in Frege○ mutable? Mutable s X
○ nullable? Maybe (...)
○ exceptions? (Ex1 | Ex2 | …)
○ side effects? ST s (...)
Compiler facts
● multi pass
● pass :: StateT Global IO a
● records information about compiled module in the
form of Java annotations
● creates and compiles Java source code
● concurrent -make option
● IDE friendly
Important Compiler Passes
● Lexer :: String -> [Token]
● Parser :: [Token] -> Maybe [Definition]
● Import
● Name resolution
● Type Check
● Transformations & Optimizations
● Strictness
● generate meta data and code
Background Information
Haskell 2010 Report https://www.haskell.
org/definition/haskell2010.pdf
Implementation of FP-Languages http://research.
microsoft.com/en-
us/um/people/simonpj/papers/slpj-book-1987/slpj-
book-1987.pdf
Calling Frege Code from Java https://github.
com/Frege/frege/wiki/Calling-Frege-Code-from-Java