Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

Hi folks 👋🏽 ,

I'm following the microblogging tutorial more or less, and I'm yet to become comfortable with Unison's way of managing functions on a DB as opposed to a file, so I may be something completely wrong, but I have a simple use case 😄

I have a v1.UserRow type and I'm trying to add v2.UserRow as follows on a new empty file:

namespace com.gvolpe.miniblog.db.v2

type UserRow
  = { userId : v2.UserId,
      userHandle : v2.UserHandle,
      name : UserName,
      avatar : Optional URI }

However, ucm gives me an error message I don't understand:

 Loading changes detected in ~/workspace/unison-playground/src/cloud/miniblog/db.u.


  This case would be ignored because it's already covered by the preceding case(s):
        7 |       avatar : Optional URI }

Ideally, I would like to avoid the v2 namespace change, given that Unison cares about hashes and not names, but I was unable to change the existing function for similar reasons.

Another scenario I'm having trouble with is the following:

namespace com.gvolpe.miniblog.db

use com.gvolpe.miniblog.db.v2 PostId PostRow UserHandle UserName UserRow

type AppStorage = {
    database : Database,
    userHandleToUser : OrderedTable UserHandle UserRow,
    userPostsTable : OrderedTable (UserHandle, OffsetDateTime) PostRow,
    postsTable : OrderedTable PostId PostRow
}

createAppStorage : '{Exception, Cloud} AppStorage
createAppStorage = do
  db = Database.named "miniblog-v2"
  Database.assign db env()
  userHandleToUser = OrderedTable.named db "userHandleToUser-v2" Universal.ordering
  userPostsTable = OrderedTable.named db "userPostsTable-v2" Universal.ordering
  postsTable = OrderedTable.named db "postsTable-v2" Universal.ordering
  AppStorage db userHandleToUser userPostsTable postsTable

Unison gives me the following error and suggestions:

  Loading changes detected in ~/workspace/unison-playground/src/cloud/miniblog/db-layer.u.
  

    
    I couldn't resolve any of these symbols:
    
       19 | createAppStorage : '{Exception, Cloud} AppStorage
        .
       33 | createPost : AppStorage -> UserHandle -> Text ->{Exception, Storage, Random, Remote} PostRow
        .
       45 | createUser : AppStorage -> UserHandle -> UserName -> Optional URI -> '{Exception, Storage, Random, Remote} ()
    
    
    Symbol       Suggestions
                 
    AppStorage   com.gvolpe.miniblog.db.AppStorage
                 com.gvolpe.miniblog.db.v1.AppStorage
                 com.gvolpe.miniblog.db.v2.AppStorage

Shouldn't Unison just pick up the definition from the same namespace by default if I don't write the full namespace? I would appreciate any help, just getting started and love a lot of the features, but the editing experience has been challenging.

You must be logged in to vote

One thing that can help is to remove as much of the deep name nesting as possible, (what Paul mentioned earlier), since the namespace file directive has some pretty finicky interactions with the edit workflow..

Based on that project you shared, here's how you can move stuff to a less nested format with a few commands. Hopefully that way, the namespace file directive is less needed.

0.) Optional - do this on a branch (recommended)

miniblog/main> branch update-structure
miniblog/update-structure> 
  1. Fork your lib to the expected place near your application code - we'll remove the deep nesting next
miniblog/update-structure> fork lib com.gvolpe.miniblog.lib 
  1. Move everything in your deeply…

Replies: 5 comments · 6 replies

Comment options

I'm not sure what's going on with the first error. Do you get that even if that is the only thing in your file?

On the second one, at the moment, a namespace clause at the top of the file doesn't affect imports. You can add:

use com.gvolpe.miniblog.db AppStorage

And then you should be able to refer to AppStorage unqualified.

One other note, as a style thing, I would not put things in com.gvolpe, I'd just put them in miniblog (or at the top level if this project just has miniblog-related stuff). When you publish a project on Unison Share, it's already published under your user/org and project name and the lib.install command picks a prefix based on the user/project name and version number. You don't have to worry about naming conflicts like you do in Java where all projects share a global namespace.

cc @rlmark

You must be logged in to vote
1 reply
@gvolpe
Comment options

Do you get that even if that is the only thing in your file?

Yes, I deleted everything and type edit UserRow in ucm and still get that. Also tried a new blank file, same luck.

Awesome, thanks a lot for the other tips, will definitely put that to practice 🙏🏽

Comment options

Hey @gvolpe! Thank you for mentioning this. I see you linked your code example in the ticket, do you want to set your project to public in the settings tab? I'm happy to take a look if so.

You must be logged in to vote
1 reply
@gvolpe
Comment options

Thanks a lot @rlmark ! I just made it public, didn't realize it was private by default 👍🏽

Comment options

One thing that can help is to remove as much of the deep name nesting as possible, (what Paul mentioned earlier), since the namespace file directive has some pretty finicky interactions with the edit workflow..

Based on that project you shared, here's how you can move stuff to a less nested format with a few commands. Hopefully that way, the namespace file directive is less needed.

0.) Optional - do this on a branch (recommended)

miniblog/main> branch update-structure
miniblog/update-structure> 
  1. Fork your lib to the expected place near your application code - we'll remove the deep nesting next
miniblog/update-structure> fork lib com.gvolpe.miniblog.lib 
  1. Move everything in your deeply nested namespace upwards to the root of the project (this only works because you don't have other stuff at the root beyond your readme and the lib)
miniblog/update-structure> move com.gvolpe.miniblog .

You'll be prompted to run it twice, since things that overwrite the root of the project are more complicated for the UCM.

Then remove the extra com

miniblog/update-structure> delete.namespace com
  1. Optional, if you did this on a branch:
miniblog/update-structure> switch main 
miniblog/main> merge update-structure

resolve any issues, run update and then merge.commit.

You must be logged in to vote
2 replies
@gvolpe
Comment options

@rlmark thanks a lot for digging into this, I'll give this a try later this afternoon and report back.

@gvolpe
Comment options

I managed to follow all these steps and got things sorted, thank you once again! 🙏🏽

Answer selected by gvolpe
Comment options

Oh, for your first issue, the mysterious error "This case would be ignored because it's already covered by the preceding case(s)", that is a really rough error message... apologies for that. I'll check if there's an issue already filed for it, and if not, I'll file a ticket.

It looks like the UCM reports that in a record-type definition when one of the preceding field types is ambiguous.

As copied, this fails for me in the same way:

type UserRow
  = { userId : v2.UserId,
      userHandle : v2.UserHandle,
      name : UserName,
      avatar : Optional URI }
-- produces the weird error

But if you fully prefix the versioned type names, this resolves for me (against the current main branch of your project)

type UserRow
  = { userId : com.gvolpe.miniblog.db.v1.UserId,
      userHandle : com.gvolpe.miniblog.db.v2.UserHandle,
      name : com.gvolpe.miniblog.db.v2.UserName,
      avatar : Optional URI }
}

Our record types are on the roadmap for a big change in the future. Thank you for surfacing this.

You must be logged in to vote
2 replies
@rlmark
Comment options

rlmark Apr 30, 2025
Collaborator

Oh! Additionally, I see you were iterating on v2 of the UserId and that is the one that you wanted to refer to in your example.

Creating a type whose constructor expects a nullary type (zero type constructors) is probably the root of the issue (obfuscated by our error message).

It looks like this is a minified structure of your type:

type V4 =

type UserId = UserId V4

type MyRecordType
  = {
    a : UserId,
    b: Nat
  }

I think the V4 nullary type from the UUID library is just meant as a phantom type to tag other types.

@gvolpe
Comment options

Oh thanks, this was the source of the issue then, it was driving me crazy 😄

Comment options

The issue about the confusing error message when nullary types are referenced in record types has been captured here: #5671

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Q&A
Labels
None yet
3 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.