Arc Forumnew | comments | leaders | submitlogin
2 points by Pauan 4303 days ago | link | parent

By the way... because they're (mostly) transparent and you can easily have multiple types attached to a single blob of data, you can use the type system to attach any arbitrary metadata you want. I can't help but feel that there's some connection there to monads...

I also just realized it might have some interesting uses as an alternative to exceptions. Rather than throwing an exception, you would instead return an object that has been tagged with an "exception" type.

By default this exception type would be propagated upwards until it reaches the top of the scope, but you can catch it by using pattern matching:

  $let (exception? X) ...
    ...
I still have no clue how to handle errors in Nulan, though... error values, exceptions, Maybe type, something else...


3 points by rocketnia 4301 days ago | link

"By the way... because they're (mostly) transparent and you can easily have multiple types attached to a single blob of data, you can use the type system to attach any arbitrary metadata you want. I can't help but feel that there's some connection there to monads..."

Yep! There's a pretty close connection to comonads, the opposite of monads. Comonads are for structures that can be unwrapped into a value at any time, but which can also be transformed without unwrapping by... confusingly, sending them a function that would unwrap them.

  extract :: MyWrap x -> x
  extend :: (MyWrap x -> y) -> MyWrap x -> MyWrap y
The point is that the wrapper that appears around y is generally related to the wrapper x started with. Note that extend's function argument might actually process multiple (MyWrap x) values, all hidden inside the main (MyWrap x).[1]

To illustrate, a pair of a Kernel expression and a Kernel environment can be used as a comonad, as long as we design Kernel expressions so that they can reify arbitrary values using 'quote. The extract method is eval, and the extend method bundles up the result as a literal expression together with the original environment.

[1] Aside from a few laws this has to follow, this kind of variation of behavior is particular to the implementation of each comonad. There will typically be some special-case utilities outside the comonad interface that take advantage of these specific features.

-----

2 points by rocketnia 4301 days ago | link

"I also just realized it might have some interesting uses as an alternative to exceptions. Rather than throwing an exception, you would instead return an object that has been tagged with an "exception" type."

This is monadic. Generally if you build a program out of a lot of functions of type (x -> MyWrap y) you can probably treat MyWrap as a monad, whereas if you build it out of a lot of functions of type (MyWrap x -> y) you can probably treat it as a comonad.

---

"By default this exception type would be propagated upwards until it reaches the top of the scope, but you can catch it by using pattern matching"

In this case you might be implementing it in a monadic way, but for most purposes the language user might as well treat it as a regular side effect.

I've been pondering the question of how to make the syntax of a language generic enough to integrate user-defined side effect models as though they're built in, just like this. However, this is a rabbit hole which has prevented me from getting very much done. :-p It's also straying pretty far from this thread's topic.

-----