core-typed

Typed Clojure, an optional type system for Clojure
2020-02-16T00:07:17.071800Z

fwiw I ported something like #lang functionality to clojure. kind of lost interest because I didn't feel there was much demand for it https://github.com/typedclojure/core.typed.lang.jvm

2020-02-16T00:07:52.072600Z

but I'm personally interested in preserving clojure's evaluation model as-is as much as possible, it certainly has it's advantages. very simple.

2020-02-16T00:08:14.073100Z

it breaks down when you need to write macro-generating macros. but that's the only limit I've come across in practice

2020-02-16T00:08:27.073400Z

and macros aren't that important in clojure anyway

whilo 2020-02-16T01:26:52.073800Z

yes, that is very different in racket.

whilo 2020-02-16T01:27:04.074200Z

do you have a sense of the parts of racket you would like to see ported over?

whilo 2020-02-16T01:27:26.074700Z

people here use redex a lot to prototype languages as it seems, i have not used it it yet

2020-02-16T01:51:16.076400Z

I'm a big fan of clojure. I'm not glamouring for anything in particular from racket. I want the best parts of Typed Racket and turnstile, but tailored precisely to clojure

2020-02-16T01:52:05.076900Z

anything that helps me understand clojure more deeply, I'm really into

2020-02-16T01:53:03.077800Z

and basically everything I've learnt has been from contrasting it with racket/typed racket. so I find racket useful and interesting from that perspective

whilo 2020-02-16T01:56:03.078200Z

makes sense

whilo 2020-02-16T01:56:09.078400Z

that might be relevant: https://popl20.sigplan.org/program/program-POPL-2020

whilo 2020-02-16T01:56:28.078800Z

sorry, not the right link

whilo 2020-02-16T01:56:51.079200Z

i mean "Dependent Type Systems as Macros" on this page, somehow it is not part of the URL

2020-02-16T01:57:02.079500Z

oh yea they finally got it published

2020-02-16T01:57:04.079800Z

really exciting

2020-02-16T01:57:07.080Z

cur

whilo 2020-02-16T01:57:10.080200Z

this is an extension of turnstyle called turnstyle+

2020-02-16T01:57:51.080700Z

haven't read it yet

whilo 2020-02-16T01:57:55.080900Z

yes, i am meeting william several times a week in reading groups, we are going through his thesis at the moment

2020-02-16T01:58:27.081500Z

my wife worked on cur for a few months about a year ago

whilo 2020-02-16T01:58:44.081900Z

oh, nice

2020-02-16T01:58:52.082200Z

so I got to hear about some progress and their frustrations in publishing a previous version of that paper

2020-02-16T01:59:08.082600Z

basically reviewers saying "why isn't this agda"

2020-02-16T01:59:18.082900Z

and "this is only possible in racket => boring"

2020-02-16T01:59:39.083400Z

that's cool, is he presenting his own thesis?

whilo 2020-02-16T01:59:44.083600Z

hehe, the PL community is more partisan than the ML community even

whilo 2020-02-16T01:59:58.083900Z

we are sitting together and he is answering questions

whilo 2020-02-16T02:00:05.084100Z

we go through it chapter by chapter

2020-02-16T02:00:52.084300Z

awesome

2020-02-16T02:02:44.084500Z

"Since dependently typed languages may evaluate expressions while type checking, checking dependent types with macros requires new macrology design patterns and abstractions for interleaving expansion, type checking, and evaluation"

2020-02-16T02:03:00.085Z

sounds familiar..

2020-02-16T02:03:52.085200Z

probably should read this paper

2020-02-16T02:04:44.085600Z

tho I like to see what I invent before seeing prior research

2020-02-16T02:05:03.085900Z

I get tunnel vision once i see a solution

2020-02-16T02:06:12.086400Z

I'm also juggling expansion, type checing, evaluation, and symbolic excution

2020-02-16T02:06:39.087100Z

but it's basically the same thing I imagine. Just some extra details of clojure thrown in

2020-02-16T02:07:21.087900Z

turnstile+'s "evaluation" is probably just dependent type checking, and for me it's literally calling eval on a clojure form

2020-02-16T02:07:46.088400Z

so my symbolic execution is turntile+'s evaluation (probably)

whilo 2020-02-16T02:11:41.089600Z

that makes sense. what would be necessary to make that extensible? i.e. being able to strengthen clojure semantics by adding annotations or additional derivations and being able to plug into your pipeline?

2020-02-16T02:12:00.090100Z

example?

whilo 2020-02-16T02:13:07.091400Z

i am building bayesian inference schemes that propagate measures through your code. there can be facts you know about these numeric entities or that you can add to description of algorithms, e.g. about convergence or resource usage, that could be automatically available to the type system.

whilo 2020-02-16T02:13:54.092100Z

in a more commercial setting i imagine having world knowledge about the system and clients that are referred to in the types that might be provided through a database

whilo 2020-02-16T02:14:35.092900Z

that is what we have been discussing with our cloud service provider client. in that setting you want to ensure static guarantees over your distributed system and would like to type check your infrastructure

whilo 2020-02-16T02:15:00.093500Z

if the type information would be in something like a datalog database then this would be way easier

whilo 2020-02-16T02:15:41.094400Z

if you can then write down rules with queries on the environment instead of using the clumsy PL notation, you could build much more refined type judgements as extensions and maybe make dependent types more accessible

whilo 2020-02-16T02:16:24.094900Z

i can try to come up with more concrete examples, if this is still too vague

whilo 2020-02-16T02:17:25.095900Z

i think most type system people work with functional languages, but are amazingly primitive when they deal with the description of the logic on the type system level. they mostly use adhoc encodings to describe the rules

2020-02-16T02:17:36.096300Z

I love concrete examples

whilo 2020-02-16T02:17:47.096700Z

ok

whilo 2020-02-16T02:21:19.099700Z

let's say you assign a memory limit to a client inside of your cloud system that you track in your client-related database. you also track the memory limits of all the docker containers you can spawn on the system with kybernetes. now you do runtime checks regularly to ensure that clients to do not violate their limit. nonetheless you write nontrivial code that does scheduling and cluster allocations and it would be nice if you could prove that it does not violate the memory limits provided to it in form of the database over clients and the database over cloud containers

whilo 2020-02-16T02:24:05.100900Z

with client here i mean business client

whilo 2020-02-16T02:24:47.101600Z

it is similar to the dependently typed example of checking shapes of arrays that are passed in at compile time and ensuring you do not access them out of bounds

2020-02-16T02:25:21.102Z

ok

whilo 2020-02-16T02:25:31.102300Z

i am not sure whether this was super clear

2020-02-16T02:25:55.102900Z

I'm with you I think, how does that tie in with your extensibility q?

2020-02-16T02:26:26.103200Z

what are you extending?

whilo 2020-02-16T02:26:49.103800Z

you can first collect and extract as much information as might be helpful in the database for the type environment and others and then right rules that make use of all this information

whilo 2020-02-16T02:27:18.104300Z

type inference and execution is kind of interleaved in dependent types

whilo 2020-02-16T02:28:15.105400Z

that means if you can extend your knowledge during execution by collecting information of the environment, proving certain things in a local scope becomes much easier

whilo 2020-02-16T02:28:53.105800Z

maybe i am oversimplifying

whilo 2020-02-16T02:30:02.106900Z

but i imagine having a kind of type checking be partially done at runtime, somewhat like gradual typing

2020-02-16T02:30:11.107300Z

ah right

whilo 2020-02-16T02:30:38.108400Z

where runtime checks are introduced, but they could also then run a refined type inference to make sure that everything is adding up

2020-02-16T02:30:39.108500Z

I have no idea how to plug dependent type checking into runtime clojure evaluation

whilo 2020-02-16T02:31:11.109400Z

do you have a typed eval?

2020-02-16T02:31:16.109500Z

and I guess that's the big distinction between my work and turnstile+? their evaluation is literally runtime?

2020-02-16T02:31:35.109800Z

probably not, what would that look like?

2020-02-16T02:31:43.110Z

like, eval with an expected type?

2020-02-16T02:32:04.110200Z

my "evaluation" is symbolic

whilo 2020-02-16T02:33:17.110500Z

right

2020-02-16T02:33:30.111100Z

are you asking if typed clojure implements an interpreter?

whilo 2020-02-16T02:33:37.111300Z

i am not sure whether their evaluation is at runtime

2020-02-16T02:33:53.111800Z

hmm ok. I thought that's what dependent type checking meant

whilo 2020-02-16T02:33:58.112100Z

i am asking whether you could rewrite part of the code before it goes into eval

2020-02-16T02:34:01.112200Z

not well versed in it myself

2020-02-16T02:34:11.112500Z

ah

whilo 2020-02-16T02:34:45.113400Z

i think so too, but i have to check more precisely what they do. we are not at turnstyle yet in the reading group, i have just heard about the paper a few weeks ago

2020-02-16T02:35:29.114100Z

yea you can emit custom code from a typing rule. but that's not a good idea because (unlike turnstile) core.typed isn't always in charge of expansion

2020-02-16T02:35:53.114700Z

which is why I dabbled in #lang's for clojure, to hook core.typed into load/require

2020-02-16T02:36:34.115400Z

well, if you used a typed #lang in clojure that always enforced type checking on load, it would be a good idea

2020-02-16T02:36:57.115900Z

and the extension points would be similar to turnstile's I imagine

whilo 2020-02-16T02:37:20.116200Z

hmm

whilo 2020-02-16T02:41:51.117500Z

to rephrase on a high-level, i think an extensible static analysis stack allows to join the type inference with a general proof system over a rich set of domains if the basis for the logical inference rules is a shared logic programming language like datalog

whilo 2020-02-16T02:42:32.118300Z

datalog is also used for reachability analysis and there are some attempts to use it for type systems, but in clojure land we also have our domain data in a powerful datalog database

whilo 2020-02-16T02:43:57.119Z

(i.e. datomic)

whilo 2020-02-16T02:46:39.121100Z

what do you mean with extension points exactly?

whilo 2020-02-16T02:46:42.121400Z

watching their talk now

2020-02-16T02:47:04.121800Z

like you can define a typing rule for macro invocations and primitives

2020-02-16T02:47:18.122100Z

that's where you plug into the type checker

2020-02-16T02:49:15.123200Z

I'm not clear what exactly you want to "plug into my pipeline". the compilation of rules to datalog?

whilo 2020-02-16T02:50:04.123800Z

i think the rules themselves could contain datalog, it would actually make more complicated rules more explicit

whilo 2020-02-16T02:50:29.124300Z

at least i have found some of the notation changing between papers and confusing when the rules do tricky things

whilo 2020-02-16T02:51:44.124600Z

i mean the environment is effectively a database

2020-02-16T02:52:15.124800Z

type environment?

whilo 2020-02-16T02:52:22.125Z

yes

2020-02-16T02:52:26.125200Z

huh

2020-02-16T02:52:42.125500Z

sounds like occurrence typing where the environment is a set of propositions

2020-02-16T02:52:58.125900Z

at least it sits close to that in my brain

whilo 2020-02-16T02:53:22.126200Z

can you describe this position a bit more?

2020-02-16T02:55:01.127900Z

yea so instead of the normal type environment which is a sequence of mappings from var=>type [x : Int, y : Bool], you use propositional logic to represent the current environment. atomic propositions are statements of the form "x is of type t". and you can && and || them any way you like

2020-02-16T02:55:20.128400Z

like {"x is type Int", "y is type Bool"} is a proposition env

2020-02-16T02:55:30.128800Z

and you would query the env to find the type of x

2020-02-16T02:55:44.129Z

{"x is type Int", "y is type Bool"} |- x : Int

2020-02-16T02:56:21.129800Z

and the rule for looking up in the type environment does constraint solving (model checking IIRC?) to determine the type of x

2020-02-16T02:56:43.130300Z

you can have interesting props like ("x is type Int" || "y is type Bool")

2020-02-16T02:57:57.131800Z

and then if you type check (if (integer? x) e1 e2) you can update the then branch with the prop "x is type Int", which reduces the env to "x is type Int", and the else branch with !"x is type Int" (negation) which reduces env to "y is type Bool"

2020-02-16T02:58:30.132400Z

check out "Logical Types for Untypable Languages" Tobin-Hochstadt & Felleisen for intro

2020-02-16T02:58:57.132900Z

also Andrew M Kent has a bunch of ideas simplifying the original paper

2020-02-16T02:59:19.133200Z

so this sounds like adding statements to a database

2020-02-16T02:59:39.133700Z

and then querying the database to get the type of bindings at a particular context

2020-02-16T02:59:54.134100Z

the intro/elim rules sounds similar

2020-02-16T02:59:58.134400Z

for environments

whilo 2020-02-16T03:01:48.135900Z

yes, that is very related, although Datalog itself provides a programming language to describe simple inference rules over relations extending on pure propositional logic. it is still first order though and some restrictions on mixing recursion with negation to stay terminating.

whilo 2020-02-16T03:02:43.136700Z

it would be like a base language for inference that can be extended by more rules, either in datalog or by ones doing more fancy logical constraint resolution

2020-02-16T03:04:05.137400Z

that would be useful for implementing occurrence typing. I tried using minikanren to do it once https://github.com/frenchy64/miniKanren-occurrence-type-inferencer

2020-02-16T03:04:58.138400Z

erm that link might be garbage, can't find the original

whilo 2020-02-16T03:05:01.138500Z

right. minikanren would be like prolog. the problem is that it does not necessarily terminate, so you could easily have an undecidable type system then

2020-02-16T03:05:51.139500Z

yea I had a hell of a time getting simple things to run quickly or even terminate

whilo 2020-02-16T03:06:21.139900Z

yes, that looks very much like the same line of thought

whilo 2020-02-16T03:06:51.140500Z

the very pragmatic benefit i see from using a datalog database, is that we know how to populate it from everywhere with information

whilo 2020-02-16T03:07:21.141Z

what is your opinion about this direction of thinking?

2020-02-16T03:08:12.142300Z

don't know datalog. I like the direction of somehwere inbetween hand-written and minikanren

whilo 2020-02-16T03:08:15.142400Z

(or more precisely, datalog is compositional over multiple data sources, datahike for instance can join data from everywhere, locally, a cluster db or one running for another party on AWS)

whilo 2020-02-16T03:09:01.143200Z

i think you still need to be able to write custom inference logic, because type systems very much are at the boundary of making logic programming tractably enough to handle programs

2020-02-16T03:09:28.143900Z

yea. it sounds challenging. I g2g tho, chat later!

whilo 2020-02-16T03:09:37.144300Z

sure

whilo 2020-02-16T03:09:44.144500Z

have a nice evening

whilo 2020-02-16T20:04:31.148400Z

regarding that it would be challenging, i am mostly thinking of instead of storing the environment in a hash-map to store it in an in-memory datalog database (could be datascript) and just start with using the pull syntax to get items out, practically the same as for a hash-map. but once the environment is stored in that way, one would have the freedom to a) use datalog queries and rules selectively when a more complicated invariant is supposed to hold in the type environment and, independently, b) expose immutable snapshots of this environment also to the runtime code in case it declares its interest (intertwining compile and runtime more effectively).

whilo 2020-02-16T20:05:10.148900Z

datascripts motto is literally to make using datalog as easy as using a hash-map 🙂

whilo 2020-02-16T20:05:21.149100Z

(and as performant)

whilo 2020-02-16T20:06:11.149500Z

the goal is by no means to write the full type system in datalog. it is not expressive enough for that