FAQ's for abilities

Can I define an ability which references other abilities?

You cannot, at present, define an ability that directly specifies another ability requirement in its request constructors. Let's say I wanted to write a Cache ability. I might want to express something like:

-- 🙅🏻‍♀️ you can't do this
ability Cache k v where
  get : k -> {Cache k v, IO} v
  put : k -> v -> {Cache k v, IO} ()

After all, I know it's likely the users of my service will want to do IO as a part of handling their get and put requests. However, we can't specify that in the ability definition. The preferred way to allow for a Cache ability to perform IO and exceptions would be to write a handler that interprets theCacheability into theIOability.

What doesRequestmean?

Thebase.Requesttype is the type that Unison uses to model therequest constructorsof an ability.

In the expressionhandle !myEffect with myEffectHandlerthe termmyEffectHandlerwould have a type which lookssomethinglikeRequest (MyEffect) a -> a- The exact semantics are described in thelanguage guide section on handlers.

When defining your own handlers you might see thebase.Requesttype, but callers of handler functions shouldn't typically need to manage it directly.

Why can't an ability be at the "top-level" of a value? As in:myTerm = printLine "Hi"

Currently values at the "top level" of a program have to be pure, so it's more common to seedelayed computationsthat contain abilities (expressed with the single quote syntax). This may change in a future version of Unison. Think of the ability constraint as a constraint onthe function arrowas opposed to a constraint on a value.

How do I test something which requires the IO ability?

Run a single test which performs IO with theio.test command.Theio.testcommand expects adelayed computationwithIOas an ability requirement. The rest of the Unisontesting conventionsremain unchanged.

You can also test functions which perform IO with Unison'stranscriptsby interleaving Unison code which performs IO with UCM fenced codeblocks that call theruncommand.

A document about writing Unison transcriptscan be found here.

What's the relationship between abilities and monads?

That deserves a longer discussion.We'll be covering that soon.🤓

But for nowcheck out this gist!

I see some code which leaves off the ability requirements in an ability declaration, what gives?

When defining an ability's operations, it's often a nice shorthand to leave off the implied ability requirement—that is, the{Abort}inabort : {Abort} a—afterall, we know that an ability operation will be performing the ability in question and will require a handler. Unison will fill that in for us if we omit it, so we could have also defined the type signature of the abort operation asAbort.abort : x.

🚧🚧 🏗 More coming soon 🚧🚧