Commit 3232e509 authored by Nicolas Lenz's avatar Nicolas Lenz ❄️
Browse files

A lot of ideas

parent 36466589
Loading
Loading
Loading
Loading
+98 −18
Original line number Diff line number Diff line
@@ -23,6 +23,30 @@ Inspired by the Zen of Python principles, these are the general paradigms the la
- Constructor identifiers: `[A-Z][A-Za-z0-9_]*`
- Operator identifiers: `[!#$%&*+-/<>?@^|~]`

### Literals

Lists, Sets, Vectors, Arrays etc. all need simple literal syntaxes.

- Simply overloaded lists? Difficult for type inferring
- Explicit typed syntax? `[list|1 2 3]`, `[set|4, 5, 6]`?

### Application

- Normal prefix application just as in most functional languages with a simple blank
- The case of infix operators
    - Do we want infix at all? Probably yes – in some cases it improves legibility and reduces need for parentheses
    - So – do we want default infix operators at all?
        - Lisp & Co don't have it, even `+` is prefix by default
        - I like that on a subjective level
        - [Polish notation](https://en.wikipedia.org/wiki/Polish_notation) instead of simple left-associativity for less parenthesis? Probably not a good idea
        - It would simplify parsing and special characters could be used care-free in any identifier
    - In any case, I want some way to infix any function. Which syntax?
        - `1 <+> 2`: My favorite, looks good and fitting, you could interpret the angles as arrows pointing to the arguments.
        - `1 \`+\` 2`: The Haskell syntax. Hard to type and not really pretty.
        - `1.+ 2`: The record syntax. Would need no extra syntax construct and one character less, but looks weird, to be honest. Might also be confusing.
        - What about `$`?


### Misc

- Infix syntax?
@@ -56,6 +80,7 @@ Inspired by the Zen of Python principles, these are the general paradigms the la
  - In general, probably yes.
- Records in Haskell are deeply flawed. Fix that, they're really importent in practice! Bring in the dot operator (as some people also did for Haskell).
- Don't concentrate on actual types and data, but rather on "capabilities"? <http://degoes.net/articles/kill-data>
- Require explicit type signatures or not? Is it even possible to infer everything sufficiently with dependent types?

## Logic

@@ -70,12 +95,12 @@ Inspired by the Zen of Python principles, these are the general paradigms the la
## Proofs

- Possible, but no priority – it isn't meant to be a proving tool
- [Curry-Howard-Isomorphism](https://de.wikipedia.org/wiki/Curry-Howard-Isomorphismus)
- How to handle trait/typeclass laws
- [Curry-Howard correspondence](https://en.wikipedia.org/wiki/CurryHoward_correspondence)
- How to handle trait/typeclass laws safely and usable?

## Interaction

Interaction (with users, windows, servers, ...) is a very important thing in programming. Unfortunately, it is quite awkward (especially for beginners) in many functional languages. Find better solutions working without loads of monad transformers.
Interaction (with users, windows, servers, ...) is a very important thing in programming. Unfortunately, it is often quite awkward (especially for beginners) in many functional languages. Find better solutions working without loads of monad transformers.

Good GUI solutions are important. Haskell still has no reasonable GUI solutions, which is really hindering adoption. Interaction-oriented language design could help.

@@ -107,10 +132,47 @@ Maybe a Haskell2Katrin converter for easy switching?

Should be implicit in pure calculations and easilty explicitly possible for IO.

- [async](https://www.stackage.org/lts-13.27/hoogle?q=async) looks nice
- Is automatic concurrency on pure calculations optimal? Is manual intervention needed or can everything be inferred? Look into how GHC does it.

## Compiler

Implement a algebraic compiler using `megaparsec` for parsing in Haskell and later write a compiler in Katrin itself.

### Architecture

Katrin code ist first parsed into a normal abstract syntax tree. This is then transferred into KatrinLite, which is essentially a desugared version of Katrin. KatrinLite is then translated to KatrinCore, which is a basic representation based on the lambda calculus without any advanced features. This is then compiled to an external intermediate language which can be used with a external compiler to produce machine code.

- [Idris2](https://github.com/edwinb/Idris2) uses »quantitative type theory« as base for the core language, look into that
- [System F](https://en.wikipedia.org/wiki/System_F) (extended for GHC with GADTs to System F~c~)
- Type-checking on KatrinLite or KatrinCore?
- Optimizations on KatrinLite or KatrinCore or both? KatrinCore should be optimal for this, while some simplifications of course need to be performed when compiling Lite to Core.
- Is using two intermediate languages even helpful?
    - **Pro:** Katrin syntax and sugar can be changed easily, only compilation to the feature-wise very close Lite representation must be changed
    - **Pro:** Different syntaxes could be easily added
    - **Con:** More complicated compilation, maybe speed loss
    - Idris2 also does this: They have a intermediate (TTImp) and a core language.
- Do we need a runtime system to be linked against? Probably. Look into the Haskell runtime system.

Which intermediate language could be used to produce binaries?

- [GraalVM](https://en.wikipedia.org/wiki/GraalVM)
    - Looks really promising
    - Supports JVM and native
    - Support for mixing with any programming language – being able to use Java, Python etc. libraries could be a *huge* advantage
- C-- (used by GHC)
    - Looks kind of obscure and doesn't really seem to be maintained.
    - No JVM or other backends, which would need to be built separately.
- LLVM Intermediate Representation
- Some functional language with a native compiler, as used by Idris2, should also be considered
    - [Racket](https://en.wikipedia.org/wiki/Racket_(programming_language)) (seen in FOSS-AG)
    - [Chicken Scheme](https://en.wikipedia.org/wiki/Chicken_(Scheme_implementation))
    - [Chez Scheme](https://en.wikipedia.org/wiki/Chez_Scheme)

Do we want a JavaScript or WebAssembly backend?
    - Web development is too different to be captured in one and the same language that was primarily made for application development (or is it?)
    - But a JavaScript backend could be useful anyway for library functions to be used by other languages (e.g. PureScript or Elm)

## Meta-Usability

### Tooling
@@ -119,8 +181,8 @@ Good and unified tooling right from the start is very important for a language a

One tool for everything: `katrin` command line tool is compiler, interpreter, shell, build system, formatter etc. in a single convenient place, like with Go, but less weird.

- `katrin compile test.katrin` (or `katrin c test.katrin`) compiles a single file into a binary.
- `katrin shell test1.katrin ...` starts an interactive shell with the files loaded. Just `katrin shell` or `katrin` starts a blank shell.
- `katrin compile test.katrin` compiles a file with a `main` function into a binary and can be used to create unlinked object files.
- `katrin shell test1.katrin test2.katrin …` starts an interactive shell with the files loaded. Just `katrin shell` or `katrin` starts a blank shell.
- `katrin run test.katrin` or simply `katrin test.katrin` executes the file.
- `katrin build` builds a project following the directions in the `project.yaml` file.
- `katrin test` runs a Katrin test suite.
@@ -130,7 +192,12 @@ One tool for everything: `katrin` command line tool is compiler, interpreter, sh
- `katrin doc` generates documentation (via Pandoc?).
- `katrin language-server` starts a language server for editors supporting the protocol.

YAML files are used for configuration as they're especially human-friendly.
What to use for config files?
- **YAML:** Human-friendly but ambiguous syntax and worse: [ambiguous semantics](https://github.com/cblp/yaml-sucks), might not be a good idea to support that
- **TOML:** Already used by Rust and looks nice, tailor-made to be used in config files, well-known syntax, better spec. My current favorite
- **Something native:** Should be avoided, but still a possibility
- **XML or JSON:** No.
- Are there even other alternatives?

### Debugging

@@ -139,12 +206,22 @@ Debugging needs to be easy and comprehensive.
- Tracing option that outputs what functions were called with what values in what order, without changing the code
- Debugger with breakpoints?

## Misc

- Look into the various [GHC language extensions](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html)
- One of the pros of OO-programming is that you can set a paramater for a whole class and then all functions of the class can use that. Without that functions calls sometimes get awkward when you have to pass the same parameters (config, server URL) over and over again. There are ways to alleviate that, maybe find something elegant to integrate into the language?
    - Something like singletons? Constants that can be set on module load? Something like that
    - Stay functional and type-safe of course
    - Maybe dependent types can be useful for this?
    - Closures?

## Other Interesting Languages

- Haskell
- Idris
- Agda
- [Cayenne](http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.47.155) (first dependent language)
- [Cayenne](http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.47.155)
    - first dependent language, interesting paper
- [Luna](https://www.luna-lang.org/)
    - Very interesting graphical representation and design stuff
- Erlang
@@ -155,23 +232,26 @@ Debugging needs to be easy and comprehensive.
- Go
- Rust
    - Trait naming
- (Common) Lisp
    - Modern and nice ecosystem
- (Common) Lisp / Scheme
    - Homoiconicity?
    - S-expressions
    - M-expressions (never really implemented?)
- (Standard) ML
- Clojure
- F#
- Scala
- Kotlin
- Java (ewww, but it's popular, so...)
- C#
- Smalltalk
    - [Reflection](https://en.wikipedia.org/wiki/Reflection_(computer_programming))
- OCaml
- Coq
- Nix (not a programming languae per se)
- Nim
- Elm
- PureScript

## Misc

- Look into the various [GHC language extensions](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html)
- One of the pros of OO-programming is that you can set a paramater for a whole class and then all functions of the class can use that. Without that functions calls sometimes get awkward when you have to pass the same parameters (config, server URL) over and over again. There are ways to alleviate that, maybe find something elegant to integrate into the language?
    - Something like singletons? Constants that can be set on module load? Something like that
    - Stay functional and type-safe of course
    - Maybe dependent types can be useful for this?
    - Closures?
- [PureScript](https://en.wikipedia.org/wiki/PureScript)
    - uses `Effect` of `IO`, look at that
- TypeScript
- Dart
+1 −0
Original line number Diff line number Diff line
{-# LANGUAGE RecordWildCards #-}

-- | Contains algebras, types and folds for KatrinCore, the intermediate language for Katrin.
-- This is tightly based on the lambda calculus and the base target which is then evaluated.
module Katrin.Core where

import Data.Text (Text)

src/Katrin/Lite.hs

0 → 100644
+2 −0
Original line number Diff line number Diff line
-- | Contains algebras, types and folds for KatrinLite, the desugared version of Katrin.
module Katrin.Lite where