|
| tm-guimaraes wrote:
| The promises are great, but will it deliver? It's seems the
| language has a really huge scope with lots of hard problems to
| solve.
|
| The thing I loved about golang was that it's just "good enough"
| in lots of areas instead of being the best or perfect. That
| allowed more time ti works on other parts of an ecosystem.
|
| But since Tao is an hobby project, i just hope the author goes
| nuts and enjoy working on all those things. It is indeed a cool
| lang.
| zesterer wrote:
| I am indeed "going nuts"!
|
| As mentioned in the README, I don't see Tao as a production-
| quality language (at least, for the foreseeable future). I'll
| leave that to the experts. Instead, I'm more interested in
| exploring the limits of new language design ideas (effect
| systems in particular). There are already a few interesting
| things Tao does that I've not seen elsewhere.
| landonxjames wrote:
| Came across this post [0] by Graydon Hoare (original author
| of Rust and member of the Swift team) in an HN comment the
| other day. Lots of interesting discussion about future paths
| for language design work, including some discussion of
| Effects Systems.
|
| Curious how Tao is pushing the limits on that front?
|
| [0] https://graydon2.dreamwidth.org/253769.html
| zesterer wrote:
| > Curious how Tao is pushing the limits on that front?
|
| I don't want to put emphasis on "pushing the limits"
| because I'm still very new to language design and mostly
| self-taught. There are bigger and better languages pushing
| the envelope further than Tao!
|
| That said, I've been experimenting with:
|
| - Expressing totality and type inhabitance in the type
| system
|
| - Effect systems (including user-defined effects, effect
| handling, parametric effects, lowering to monadic IO, etc.)
|
| - Typeclass inference via typeclass variables (Tao can
| handle several cases that are ambiguous even in Rust, such
| as the following: https://github.com/zesterer/tao/blob/mast
| er/examples/debug.t...)
| skavi wrote:
| would you mind explaining the linked code?
| zesterer wrote:
| The code is a bit of a gimmick, not really the sort of
| thing you'd have in a real program. It's just there to
| demonstrate that the compiler doesn't need explicitly
| telling which typeclasses associated types correspond to.
| That said: fn show_negative A : A ->
| Str where A < Neg, A.Output <
| Neg, A.Output.Output < Neg,
| A.Output.Output.Output < Neg,
| A.Output.Output.Output.Output < Show, =
| a => (----a)->show
|
| This is a function, called `show_negative`, that is
| generic over a type, `A`. The function takes an instance
| of `A` and returns a `Str` (string).
|
| In terms of implementation, the function is quite simple:
| it just negates the input value a bunch of time and then
| `show`s it as a string using the `Show` typeclass
| (equivalent to Haskell's `show`: https://hackage.haskell.
| org/package/base-4.16.1.0/docs/Prelu...).
|
| Arithmetic operations such as negation are defined using
| typeclasses. Here's the definition of `Neg`:
| class Neg = => Output => neg :
| Self -> Self.Output
|
| This means that types that can be negated must provide
| two things: an output type produced when they're negated,
| and a function that actually performs the negation. For
| example, `Nat` (natural number) looks like:
| member Nat of Neg = => Output = Int
| => neg = fn x => (implementation omitted because it's a
| built-in intrinsic)
|
| i.e: when you negate a `Nat`, you get an `Int`.
|
| The `where` clauses on the `show_negative` just
| constrains the output type of negating the `A` in such a
| way that _its_ output type is also constrained, in a
| chain, with the final type in the chain being
| `show`-able.
| LelouBil wrote:
| A couple of months agow I had never tried functional programming
| languages. Having learned Rust in the past year (and loving it )
| made me want to try out Haskell since I always wondered about
| functional languages and I likes Rust's strong type system.
|
| I go a bit dissappointed with Haskell, but right now I'm reading
| Tao's README and this looks like everything I've ever wanted !
| I'm gonna try it out right now.
| throwaway17_17 wrote:
| Can you expand on what disappointed you about Haskell. I'm not
| looking to convert you or anything, just curious.
| okasaki wrote:
| Sorry, what's that font in the github screenshots?
| zesterer wrote:
| Iosevka Fixed Slab Semibold
| kortex wrote:
| Nice work! Looks super interesting and rewarding to work on.
|
| Is the namesake "tao" meaning "the way"? Or perchance a nod to
| Terry Tao?
| zesterer wrote:
| > Tao or Dao is the natural order of the universe whose
| character one's intuition must discern to realize the potential
| for individual wisdom
|
| It echoes how I feel when I write programs in languages with
| strong static type systems: that of the compiler almost
| fatalistically leading me towards a solution that naturally
| fits the problem space. A metaphor I like to use is that of an
| artist knocking away pieces of marble to reveal the statue that
| was always there beneath.
|
| And, yes, it's great fun to work on! Everybody should give
| writing a compiler and designing a language a try!
| pjmlp wrote:
| I guess not to mix with Tao, next gen OS for Amiga, based on
| bytecode as distribution format.
|
| https://www.edn.com/amiga-reborn-via-tao-alliance/
| lloydatkinson wrote:
| Somewhat familiar with FP and enjoy some of its benefits in my
| projects but I haven't really used a full blown FP language like
| Haskell. What exactly is a type class? I haven't found an
| explanation that makes a lot of sense to me. I think at one time
| I believed them to be some kind of contract like an interface in
| a OO language.
|
| Can someone explain?
| zesterer wrote:
| A typeclass (or in Rust, a trait) is something that describes a
| set of behaviours that must be implemented by a type (in OOP
| languages, abstract classes are broadly equivalent).
|
| For example, the typeclass `Eq` describes how values of a type
| might be compared for equality. class Eq =
| => eq : Self -> Self -> Bool
|
| The typeclass requires that types conforming to it provide a
| function, `eq`, that takes two instances of itself and returns
| a bool (indicating whether the instances are equal). And member
| of this typeclass might look like: for A, B
| member (A, B) of Eq where A < Eq, B <
| Eq, = => eq = fn (a0, b0), (b0, b1) => a0
| == a1 && b0 == b1
|
| You can read this as "for any two types, A and B, a tuple of
| both can also be compared for equality provided both A and B
| can themselves be compared for equality"
|
| Typeclasses become useful because they allow you to constrain
| generic type parameters. For example, we can now write a
| function that determines whether a list contains a matching
| value: fn contains A : A -> [A] -> Bool where
| A < Eq, = | _, [] => False \ k,
| [x .. xs] => x == k || xs->contains(k)
|
| All of this is checked at compile-time by the compiler,
| ensuring that the function can only be called with types that
| can be compared for equality.
| lmm wrote:
| One of the things that's hard to follow is that people conflate
| typeclasses and typeclass instances.
|
| So, the typeclass itself is like an interface, but rather than
| having classes that implement that interface directly, you have
| typeclass instances which are like an adapter between a value
| (struct) and the interface - or like a virtual function table.
| You know how a class instance is essentially a struct + a
| (pointer to a) virtual function table? Imagine making those two
| pieces more distinct in code - the typeclass instance is the
| stanadlone virtual function table.
|
| So your object state is more exposed - you can't really have
| private fields in this paradigm since your state is just a
| struct value. But it's clearer what's what, and it's much
| easier to adapt types to interfaces even when the authors
| didn't know about each other, since the typeclass instance can
| be defined separately from both the typeclass and the value
| type (although there are possible inference problems with
| this). So lots of secondary cross-cutting functionality
| problems where OO languages tend to end up with an ad-hoc type
| registry (e.g. serialization or database mapping - just look at
| what projects like jackson-datatype-joda or joda-time-hibernate
| have to do to get themselves registered) are easier to solve in
| this model.
| galaxyLogic wrote:
| What about OOP classes and inheritance? Data hiding? Modules?
| zesterer wrote:
| Tao has typeclasses (like Haskell) that allow for compositional
| parameteric polymorphism. It also has data types (records, sum
| types, etc.) and functions, but deliberately does not bundle
| the two together.
|
| There is no module system yet (only a temporary C-like #include
| system): that's on my list of things to work on!
| toastal wrote:
| I don't understand what the possible use case for using a \ for
| the final bar for sum types would be. It would just make it a
| diff to add a new item at the end. I was hoping it had Unicode
| support looking at the example screenshot, but no, it's just a
| ligature font confusing users.
| zesterer wrote:
| Tao isn't indentation-sensitive, so nested `match` expressions
| are ambiguous without the trailing \ branch.
|
| I don't know whether I'll keep this syntax though. I'm
| increasingly wondering whether it's better to just bite the
| bullet and go all in with indentation sensitivity.
|
| That said, the existing \ syntax can be quite nice to read:
| https://github.com/zesterer/tao/blob/master/lib/parse.tao#L5...
| ratww wrote:
| The \ syntax is my favorite part so far, I'm definitely gonna
| copy it for my toy language, hope that's ok ;)
| zesterer wrote:
| Go for it! IIRC it was suggested by someone else in the
| #langdev channel on the Rust Community Discord, so I can't
| claim to own the idea.
| catlifeonmars wrote:
| Why not just require parents for nested cases? IMO this is
| fairly unambiguous, even to people unfamiliar with a
| particular language.
| zesterer wrote:
| In a previous revision of the language, I did!
| (https://github.com/zesterer/tao/tree/old). I decided
| against it because, in short, I find the trailing
| delimiters to be quite ugly.
|
| Because this is purely a personal project, I'm thankfully
| not constrained by such mundane concerns as "ergonomics"
| (unless such concerns relate to me while I'm working with
| it). I think Pythonic syntax is probably the way to go
| long-term though...
| patrickkidger wrote:
| Personally I'm a big fan of Julia's syntax here.
| Indentation-insensitive with the use of the word "end" as
| the terminator for all types of block. In practice you
| can lay it out like Python, and the "end"s help you keep
| track when e.g. you need to place a single expression
| after some deeply-nested blocks.
| solatic wrote:
| > Totality
|
| Best of luck. Dhall is a current language with totality, but it
| runs into impossibly high memory requirements as a result. We had
| CI workers with 16 GB RAM run into out-of-memory issues because
| of the sheer size of the totally expanded type space (sum types
| of types which are themselves sum types of types which are
| themselves sum types etc... Exponential growth is easy).
|
| I appreciate that this is scoped as a hobby project for now, not
| recommended for production, so like I said, best of luck :)
| atennapel wrote:
| I'm not sure what you mean with totally expanded type space.
| But it sounds like Dhall has an issue with
| unfolding/normalisation.
|
| Totality shouldn't have any special impact on memory usage as
| far as I know. It just restricts the kind of recursive
| functions and data types you can write.
| iamwil wrote:
| What were the series of resources or readings that you did to
| help you create Tao?
| zesterer wrote:
| There wasn't really any single resource I read. Frustratingly,
| I find it quite difficult to read research papers (I'm told
| it's a skill acquired with practice, but it's something I've
| never gotten into). Most of the implementation is the product
| of several rewrites and false-starts, along with the occasional
| hint I've read about here or there on the web.
| darthrupert wrote:
| Hardly ever is "good REPL" one of the features of these new
| languages. Do they think it's irrelevant or is making such a
| thing too difficult compared to all these more CSy features?
| zesterer wrote:
| REPLs are often difficult to reconcile with AoT compilation and
| static analysis, particularly in the context of things like
| type inference (at least, in a way that preserves semantics).
| It's on my mental todo list, but not a priority for me.
| pohl wrote:
| Do you suppose that might be an outmoded historical bias? I'm
| wondering if maybe the advancement of hardware has made it so
| that the costs of AOT compilation and a type system should no
| longer stand in the way of delivering a reasonable REPL
| experience. Swift's "playgrounds" seems to do alright -- a
| real outlier in this regard.
| skavi wrote:
| Haskell has a REPL. No idea whether it's considered good
| though.
| catlifeonmars wrote:
| How fast is the compiler? In many cases a report can just be
| syntactic sugar for compiling and running an accumulating log
| of source code lines. It's not really important how it works
| under the hood as long as it's mostly transparent to the
| user.
|
| As a side effect, it might also be a good way to keep your
| compile times down.
| substation13 wrote:
| What if one of those lines fires the missiles?
| zesterer wrote:
| Fast enough for this approach to work for small examples.
| For longer examples, I'm less confident: I've yet to
| implement a proper module system (other than a slightly
| more principled version of C's #include) so this currently
| means compiling the entire standard library on every REPL
| line. Thankfully, the compiler can still handle this within
| about 100 milliseconds on my machine. Perhaps when I have a
| more rugged module system I can look into this more, thanks
| for the suggestion!
| darthrupert wrote:
| That's not even close to being adequate for the kinds of
| things good REPLs are good for.
| shirogane86x wrote:
| This looks great! I've actually been experimenting with making a
| functional language too, in rust - so I'm probably gonna read
| through the code soon! Also, those error messages look really
| good - I'm totally gonna try ariadne and chumsky out :)
| zesterer wrote:
| Good luck! Feel free to open a discussion topic or issue if you
| have any questions!
| throwaway17_17 wrote:
| Since someone brought it up, and since I don't speak rust...
| are the error message formats (i.e. the lines and crossings)
| made by a rust library or did you implement them? They are
| certainly visually nice.
| zesterer wrote:
| They are made by a Rust library, but it's a library I wrote
| for this project (now used by others too):
| https://github.com/zesterer/ariadne
| magicalhippo wrote:
| Great readme, and definitely made me want to play with it. I was
| raised on procedural programming and never really got into proper
| functional programming, but somehow this just clicked for me.
| erezsh wrote:
| Asking as a complete newbie in this paradigm, but what's the
| benefit of writing factorial like this? fn
| factorial = | 0 => 1 \ y ~ x + 1 => y *
| factorial(x)
|
| Instead of | y => y * factorial(y-1)?
| zesterer wrote:
| Subtraction of natural numbers is non-total, and can result in
| negative numbers, which cannot be represented as a natural
| number. Most languages throw an exception, panic, etc. None of
| these are solutions I'm happy with.
|
| In Tao, natural numbers don't support subtraction but you can
| decrement them by pattern-matching as in this example, allowing
| the compiler to 'check your workings' and statically prove that
| your program can never result in underflows.
|
| In a similar vein, you can't index directly into a list
| (because indexing is a fallible operation). Instead, you must
| pattern-match on the list and explicitly handle the empty case
| (you can also write a utility function to do this for you like
| so) fn nth : Nat -> [A] -> Maybe A =
| | _, [] => None | 0, [x ..] => Just x \
| n + 1, [.. tail] => tail->nth(n)
|
| Used like: [1, 2, 3]->nth(1) # Evaluates to
| `Some 2`
| Akronymus wrote:
| A few observations:
|
| Seems very ML/Haskell inspired.
|
| All tuples seem to require parenthesis.
|
| Definitely not ergonomic on a qwertz layout (Altough, what
| language is?)
|
| No current plans for an interactive/repl version it seems
|
| No dependant types either.
|
| Overall, pretty interesting. Definitely warrants a closer look.
| zesterer wrote:
| Pretty much!
|
| The language does support limited sugar for tuples without
| parentheses in some specific cases, such as `match` and `let`:
| let x, y = 5, 4 in ... match x, y in
| | 4, 7 => None \ _, y => Just y
|
| However, these cases only incidentally lower to tuple pattern
| matching, and deliberately hide the fact that tuples are used
| internally.
| Akronymus wrote:
| Are you planning on having something similar to computation
| expressions? Altough, I guess thats basically covered within
| the do notation.
|
| https://docs.microsoft.com/en-us/dotnet/fsharp/language-
| refe...
| zesterer wrote:
| Yes! As you say, the do notation + monads covers this, but
| I'm planning to remove it in favour of a slightly more
| general 'effect basin' syntax that I'm currently working on
| (syntactically similar to Rust's async + await, but
| generalised to all effectful operations like mutation, IO,
| etc.). Example here: https://github.com/zesterer/tao/blob/m
| aster/examples/mutate....
| platz wrote:
| > No dependant types either.
|
| You're funny
| Akronymus wrote:
| How so? I personally find dependant types to be very
| interesting, but I get that they are a PITA to implement. So,
| for me, it was simply an observation that there are currently
| no plans for dependant types. No value judgement intended.
| isaacimagine wrote:
| Not to be pendantic, but I think you made a joke without
| realizing it.
| Akronymus wrote:
| I did? I have now spent like 20 minutes trying to figure
| it out. But I still don't get it.
| macintux wrote:
| I'm guessing it has something to do with the keyword
| "either" and Haskell types, but I'm otherwise clueless.
| Every time I look at Haskell I run the other way.
| zesterer wrote:
| I think it was "value judgement" (dependent types allow
| dispatching over a value in the type system)
| maweki wrote:
| So is the language planned to be computationally complete or
| total?
|
| I was not completely clear on your definition of totality. But I
| am all for not Turing-complete models of computation that still
| do useful things.
| zesterer wrote:
| For now, just total (i.e: functions can't panic, throw
| exceptions, etc.). I'd like to explore termination analysis in
| the future though!
| samatman wrote:
| It's an unfortunate conflation between total functions and
| _total functional programming_ , which is done with non-
| terminating languages. If I'm reading you right, Tao
| currently requires functions to be total but is not designed
| to always terminate.
| zesterer wrote:
| Yes. This is something I've been thinking about a lot, as
| it happens! In particular, one of the great benefits of
| pure languages from an optimisation standpoint is that
| unused values can always be optimised away, but this is not
| the case if we treat termination (or non-termination) as a
| side effect! For now, I'm treating it as not being a side-
| effect (as does C++, although C++ goes a step further and
| treats it as straight-up UB in certain conditions). This is
| something I've still yet to nail down semantically.
| zesterer wrote:
| Hey, author here. I definitely didn't expect to see Tao on Hacker
| News. As is probably obvious, the language is _extremely_ early
| in its life, and it 's not practical to write anything but
| trivial examples in it yet. Please don't judge!
| agumonkey wrote:
| good luck
| code_biologist wrote:
| I remember a golden age of programming reddit and HN in the
| late 2000s that inspired me learn a bunch of new programming
| languages, Haskell the biggest influence among them. It seemed
| like people were always posting their own personal languages,
| lisps (I remember the hot takes on Arc lol), and such all the
| time. I have very fond memories of going through Jack
| Crenshaw's "Let's Build a Compiler" after seeing it posted a
| bunch of times, then trying to build my own language in a
| similar vein.
|
| Cheers to you, and I hope you're learning and having fun
| working on your project!
| zesterer wrote:
| Thanks!
| jrumbut wrote:
| I too remember that time and it left me terribly jaded
| about the utility of new languages.
|
| This is the first I've seen in a while where I think the
| offering hits a spot on the tradeoff continuum that is
| distinctive and where I can picture many circumstances
| where I would want to use this language (the soundness
| aspect is a big part of that).
| dmix wrote:
| Nice work on the README. Gets right to the point about what it
| look likes and what the goals are.
| yccs27 wrote:
| Tao looks super cool, and similar to the kind of language I'd
| personally make if I decided to create one. Kudos for actually
| implementing yours!
|
| Some specific questions about the language design: - Does your
| flavor of algebraic effects allow distinct effects of the same
| type (e.g. two separate int-valued `State`s)? I haven't seen
| anyone talk about this, but it seems like a potential problem
| with effects.
|
| - Do you have plans for making pattern matching extensible?
| I've thought a lot about how this could be possible with optics
| (the FP construction), but haven't found a nice solution yet.
| zesterer wrote:
| > Does your flavor of algebraic effects allow distinct
| effects of the same type
|
| Could you give an example of what you mean by this? Multiple
| effects can be combined together (although I'm still working
| on handlers for multiple effects), for example:
| effect console = input + print fn greet_user :
| console ~ () = { print("Please enter your
| name:")!; let name = input!;
| print("Hello, " ++ name)!; }
|
| > Do you have plans for making pattern matching extensible?
|
| I have no plans as of yet. Extensible pattern-matching seems
| to me to be quite hard to unify with exhaustivity. Tao
| supports most of the patterns that Rust/Haskell supports.
| throwaway17_17 wrote:
| I think GP is referring to having two effects, like State1
| and State2, both of which allow for stateful effects on int
| references, and then being able to handle the effects
| uniquely for each effect. I think the underlying type
| theoretical question would be are Tao's effects nominally
| vs. structurally typed.
|
| A more practical example would be having two state-like
| effects for use as different allocation/deallocation
| strategies.
| zesterer wrote:
| Tao's effects are nominally typed, so there's no way to
| accidentally mix them up in the way I assume you're
| describing. For example: # Define a new
| effect that yields to the caller effect yield A =
| A => () # A generator that emits numbers
| def one_two_three : yield Nat ~ () = {
| yield(1)!; yield(2)!; yield(3)!;
| } # Print the numbers to the console
| def main : io ~ () = { one_two_three
| handle yield Nat with n => print(n->show)! }
| roguas wrote:
| Designing a PL is a hard complicated process, very slim portion
| of professional programmers are able to deliver some novelty
| here. I think any judgement should be treated as merely a
| feedback on the usefulness of this language. The effort alone
| is exceptional accomplishment. Take care.
| zesterer wrote:
| Thanks for your kind words :)
| dataangel wrote:
| > A rather dogged and obnoxious opinion of mine is that the
| 'optimisation ceiling' for statically-typed, total functional
| programming languages is significantly higher than traditional
| imperative languages with comparably weak type systems.
|
| Curious about plans for this. When Haskell use exploded I
| followed a lot of the blogs talking about it someday being
| faster than C because purity made compiler reasoning easier and
| stream fusion and other things were going to change the world,
| but as time went on idiomatic Haskell never came even close to
| C. Now having a lot of performance experience I think a major
| factor is that functional languages insist on using lists for
| everything, which map poorly to hardware. Looking at your
| screenshots, it looks like it still employs the list paradigm.
| zesterer wrote:
| So... I want to preface this by saying that I'm very, very
| far from being an expert on this topic. Although Tao's
| compiler has a MIR optimiser, it only covers the basics
| (inlining, constant folding + symbolic execution, etc.).
|
| I think one of the main reasons that Haskell failed to solve
| this is actually the same reason that many lower level
| languages failed: it places too many requirements on data
| representation. In the case of C/C++ and even (to a lesser
| extent) modern languages like Rust and Swift, this is because
| they make promises about representation to the programmer
| that allow you to circumvent aspects of the language and
| still write correct code: be it transmutation, casting, field
| offsets, etc. In the case of Haskell, lists have an entirely
| arbitrary length and the language makes no effort to
| constrain this requirement in the type system, meaning that
| the compiler can only speculatively optimise a list into an
| unboxed array. In a language with dependent types, it should
| be possible to constrain the size of a list with the type
| system, allowing the optimiser to do its job without need for
| speculative whole-program analysis.
|
| The other reason Haskell doesn't quite succeed is
| monomorphisation (or lack thereof). Haskell's support for
| first-class higher-ranked types means that the language can't
| feasibly make promises about monomorphisation, and as a
| result it needs to revert to boxing and dynamic dispatch far
| more than it really should. Conversely, Tao is designed to
| monomorphise in all cases from the start.
|
| Rust demonstrates that functional programming (and in
| particular, programming with higher-order functions) is more
| than possible to optimise very well, and it does this by
| promising monomorphisation through the type system, allowing
| the compiler to aggressively perform static dispatch and
| inlining.
|
| From what I've seen, GHC also fails to pick a lot of low-
| hanging fruit. The last time I checked (perhaps this has
| since changed) GHC often struggles with things like TCO and
| inlining in relatively simple cases as a byproduct of its
| design (all functions are dynamically dispatched by default,
| with inlining being a speculative optimisation).
|
| I need to do a little more writing about exactly what ideas I
| have for Tao, but other languages of similar ilk demonstrate
| that Haskell is very far from the pinnacle of what is
| possible (for example, Koka's Perceus reference reuse:
| https://koka-lang.github.io/koka/doc/book.html#why-perceus).
| shadowofneptune wrote:
| > all functions are dynamically dispatched by default, with
| inlining being a speculative optimisation
|
| Could you please point me to other approaches to inlining?
| I am also working on a personal language and it could be
| helpful.
| zesterer wrote:
| Rust gives each closure a unique type (see the `Fn`
| trait: https://doc.rust-lang.org/core/ops/trait.Fn.html),
| allowing the compiler to always statically dispatch to
| the exact function body at compile-time. That said, this
| is a rather more explicit approach that won't necessarily
| fit everything.
| slavapestov wrote:
| I'm curious how you implement associated types and equivalences
| between them. In the most general case, this allows encoding an
| arbitrary finitely-presented monoid in the type system, and the
| word problem on finitely-presented monoids is undecidable.
| However, you mention your type checker is Turing-complete.
| zesterer wrote:
| Yep, this is the case: the type-checker allows arbitrary
| computation to occur at compilation time. You can see some of
| that here, where I've implemented peano
| arithmetic/addition/multiplication/branching using the type
| system:
| https://github.com/zesterer/tao/blob/master/examples/type-
| as... . I've not yet had the time or mental fortitude to
| implement something more non-trivial like N-queens or a
| Brainfuck interpreter, but perhaps eventually!
| slewis wrote:
| Very cool! This might be a naive question. Are your arithmetic
| patterns equivalent to dependent types, like those found in
| Idris?
| zesterer wrote:
| They're more akin to 'destructuring' natural numbers into
| successors. Consider:
|
| data Nat = Zero | Succ Nat
|
| You could pattern match on this Nat, fetching the inner Nat,
| allowing the type system to prove that all cases are handled
| exhaustively. Arithmetic patterns just extend this notion to
| the built-in Nat type.
|
| Full dependent typing is something I'd like to experiment with
| in time, but I'm not there yet.
| schaefer wrote:
| The Tao that can be told is not the true Tao.
___________________________________________________________________
(page generated 2022-07-05 23:01 UTC) |