For anyone who hasn’t used Unison’s library documentation before, you’re in for a treat:
on the home page, if you click on the @stew / http package, you’ll be taken to the readme for the package - pretty standard so far. Clicking on HttpRequest.get will then go to get‘s documentation, but for some reason it’s kinda small, with a button to reveal more. Where things get fun is if your then click on HttpRequest, you’ll see it’s documentation pop up at the top of the page, but get‘s docs are still there below; click Body and you’ll then get its documentation pushed to the top of the stack.
This is probably what most of us do with browser tabs all the time, but being able to basically dynamically create your own page of docs for the types and functions you’re trying to use, and have it all visible at once, it such a time saver.
Infix notation without operator precedence seems like a tremendously bad idea. If they didn’t want to implement operator precedence, why not use prefix notation?
It’s hard to look at this page without seeing all of the names. As I understand it, Unison’s types and packages have names, and isomorphic types are only equivalent if they have the same name. How can Unison hope to offer a better experience than Haskell or OCaml when it still has these structural issues?
isomorphic types are only equivalent if they have the same name
That’s not true. Unison has two forms of types, the common one is a structural type and that means structural equivalent types are hashed to the same thing. For example:
structural type Optional a = None | Some a
structural type Maybe x = None | Just x
These are hashed to the same underlying type. Unison doesn’t put a limit on how many names you can give a hash though, so if you defined the above, you could use either Optional or Maybe, depending on what you’ve defined/imported.
Alternatively, you can use a unique type to prevent things from hashing to the same type. For example:
unique type Suit = Hearts | Spades | Diamonds | Clubs
unique type Direction = North | South | East | West
So you can’t accidentally use a South when you meant a Spades.
Open up ucm, make a file (e.g. scratch.u) with this content:
structural type Foo = A | B | C Int
structural type Bar = B | A | C Int
isBarB : Bar -> Boolean
isBarB bar =
match bar with
Bar.B -> true
_ -> false
> isBarB Foo.A
Save it and Unison will tell you:
Now evaluating any watch expressions (lines starting with `>`)... Ctrl+C cancels.
10 | > isBarB Foo.A
⧩
true
Types are hashed independent of the package. If I define Boolean myself, it would have the same hash as base’s Boolean. I could write a function which works on “both” (because there is no both, really)
I don’t use Unison, but I didn’t understand some of this. What does “all of the names” refer to in this context? I’m also unsure what “isomorphic” means here.
Suppose that there is only one way to implement a particular type and its associated functionality. (Maybe there are multiple ways, but only one way that fits some code-style requirements.) Then there clearly is no need for multiple packages implementing that type. So, what is the point of all of the different named packages, then?
For anyone who hasn’t used Unison’s library documentation before, you’re in for a treat:
on the home page, if you click on the
@stew / http
package, you’ll be taken to the readme for the package - pretty standard so far. Clicking onHttpRequest.get
will then go toget
‘s documentation, but for some reason it’s kinda small, with a button to reveal more. Where things get fun is if your then click onHttpRequest
, you’ll see it’s documentation pop up at the top of the page, butget
‘s docs are still there below; clickBody
and you’ll then get its documentation pushed to the top of the stack.This is probably what most of us do with browser tabs all the time, but being able to basically dynamically create your own page of docs for the types and functions you’re trying to use, and have it all visible at once, it such a time saver.
https://share.unison-lang.org/@unison/code/latest/namespaces/public/base/latest/;/types/@@Nat
Infix notation without operator precedence seems like a tremendously bad idea. If they didn’t want to implement operator precedence, why not use prefix notation?
It’s hard to look at this page without seeing all of the names. As I understand it, Unison’s types and packages have names, and isomorphic types are only equivalent if they have the same name. How can Unison hope to offer a better experience than Haskell or OCaml when it still has these structural issues?
That’s not true. Unison has two forms of types, the common one is a
structural type
and that means structural equivalent types are hashed to the same thing. For example:These are hashed to the same underlying type. Unison doesn’t put a limit on how many names you can give a hash though, so if you defined the above, you could use either
Optional
orMaybe
, depending on what you’ve defined/imported.Alternatively, you can use a
unique type
to prevent things from hashing to the same type. For example:So you can’t accidentally use a
South
when you meant aSpades
.out of curiosity, what happens if I declare:
Does
Foo::A
(made up syntax) equalBar::B
?Open up
ucm
, make a file (e.g.scratch.u
) with this content:Save it and Unison will tell you:
I’ve realised an easier way to test this is in ucm:
Which is interesting behaviour. I’m not sure how Unison selects which definition to use for displaying.
Thank you for correcting me. Are packages also structural, or are packages unique?
Types are hashed independent of the package. If I define
Boolean
myself, it would have the same hash asbase
’sBoolean
. I could write a function which works on “both” (because there is no both, really)I don’t use Unison, but I didn’t understand some of this. What does “all of the names” refer to in this context? I’m also unsure what “isomorphic” means here.
Could you elaborate?
Suppose that there is only one way to implement a particular type and its associated functionality. (Maybe there are multiple ways, but only one way that fits some code-style requirements.) Then there clearly is no need for multiple packages implementing that type. So, what is the point of all of the different named packages, then?