unison icon indicating copy to clipboard operation
unison copied to clipboard

PatternMatchFailure when pattern matching function argument with ability

Open ThisFunctionalTom opened this issue 3 years ago • 6 comments

Normally when a function has multiple arguments one can pattern match with multiple arguments like this:

test: Nat -> Nat -> Nat
test = cases x, y -> x + y

> test 1 2

But once the second argument is an ability request I get the PatternMatchFailure from the compiler.

structural ability MyStream a where emit : a -> {MyStream a} ()

MyStream.toList : '{g, MyStream a} r -> '{g} [a]
MyStream.toList streamFunction = 'let
  handler : [a] -> Request {MyStream a} r -> [a]
  handler = cases
      acc, { emit x -> continue } -> handle !continue with handler (acc :+ x)
      acc, { r } -> acc
  handle !streamFunction with handler []

Matching just on the ability request works as expected:

MyStream.toList : '{g, MyStream a} r -> '{g} [a]
MyStream.toList streamFunction = 'let
  handler : [a] -> Request {MyStream a} r -> [a]
  handler acc = cases
      { emit x -> continue } -> handle !continue with handler (acc :+ x)
      { r } -> acc
  handle !streamFunction with handler []

ThisFunctionalTom avatar Jul 24 '22 15:07 ThisFunctionalTom

Here's a minimal reproduction:

myHandler : Text -> Request {Abort} a -> Text
myHandler = cases
        arg, {Abort.abort -> resume} -> "a"
        arg, {x} -> "b"

Saving that resolves to just PatternMatchFailure in ucm.

Do either of @tstat or @dolio know what's happening here?

ChrisPenner avatar Aug 08 '23 06:08 ChrisPenner

I'm not exactly sure why this is happening, but this is a compiler crash during type checking. It's not a unison pattern match failure. Something about how this function gets desugared is confusing the type checker. But I don't actually know what this code turns into internally.

dolio avatar Aug 08 '23 15:08 dolio

Here's a really simple reproduction,

I've run into this error a couple times now and had to stare at it for a bit before realizing what I did wrong.

ability Ask a where ask : {Ask a} a

provide : a -> '{Ask a} r -> r
provide a action = 
  h = cases
        {ask -> resume} -> handle resume a with h
        r -> r
  handle !action with h

Results in just:


  PatternMatchFailure

in UCM 😢

ChrisPenner avatar Feb 05 '24 18:02 ChrisPenner

My immediate guess for that example would be that the r -> r case is causing trouble, because it's supposed to be { r } -> r. The other examples don't (appear to) have that aspect, though. Do the multiple cases desugar into something similar?

dolio avatar Feb 06 '24 16:02 dolio

Sorry, forgot to point out that yes, the r -> r case is definitely the problem and it should be {r} -> r, but I'd love a better error message :D

ChrisPenner avatar Feb 06 '24 16:02 ChrisPenner

Yeah, it definitely shouldn't just crash the type checker. I'm just wondering what the common factor is. Or are there two bugs? :)

dolio avatar Feb 06 '24 18:02 dolio