question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Lack of type refinement for match case

See original GitHub issue

Compiler version

3.1.3

Minimized code

sealed trait NatT
case class Zero() extends NatT
case class Succ[N<: NatT](n: N) extends NatT

trait IsLessThan[M <: NatT, N <: NatT]
object IsLessThan:
  given base[M <: NatT]: IsLessThan[M, Succ[M]]()
  given weakening[N <: NatT, M <: NatT] (using IsLessThan[N, M]): IsLessThan[N, Succ[M]]()
  given reduction[N <: NatT, M <: NatT] (using IsLessThan[Succ[N], Succ[M]]): IsLessThan[N, M]()

sealed trait UniformTuple[Length <: NatT, T]:
  def apply[M <: NatT](m: M)(using IsLessThan[M, Length]): T

case class Empty[T]() extends UniformTuple[Zero, T]:
  def apply[M <: NatT](m: M)(using IsLessThan[M, Zero]): T = throw new AssertionError("Uncallable")

case class Cons[N <: NatT, T](head: T, tail: UniformTuple[N, T]) extends UniformTuple[Succ[N], T]:
  def apply[M <: NatT](m: M)(using proof: IsLessThan[M, Succ[N]]): T = m match
    case Zero() => head
    case Succ(predM): Succ[predM] => tail(predM)(using IsLessThan.reduction(using proof))

Output

Found:    (proof : IsLessThan[M, Succ[N]])
Required: IsLessThan[Succ[predM], Succ[N]]

Expectation

The code is expected to compile, as within that case branch, M is identified with Succ[predM].

I opened a discussion thread on contributors.scala-lang.org about this, but didn’t get any answer. So I’m tentatively filing this as a bug.

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:14 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
Bersiercommented, Sep 21, 2022

@Linyxus This is great. Now that I know about it and once the PR is in, I can make use of this pattern.

I do wonder how many people would find such a solution when in a similar situation. I know that I would never have come up with this by myself. I guess documentation can go a long way.

1reaction
Linyxuscommented, Sep 20, 2022

Currently in #14754 we only record equalities between singleton types. So we will not record a constraint like m.type <: Succ[predM]. However, by rewriting the example a bit:

def apply[M <: NatT](m: M)(using proof: IsLessThan[m.type, Succ[N]]): T = m match
  case Zero() => head
  case m1: Succ[predM] =>
    // ...

we will be able to record the equality m.type == m1.type. But this still cannot make the example work. The furthest i can go is:

case class Cons[N <: NatT, T](head: T, tail: UniformTuple[N, T]) extends UniformTuple[Succ[N], T]:
  def apply[M <: NatT](m: M)(using proof: IsLessThan[m.type, Succ[N]]): T = m match
    case Zero() => head
    case m1: Succ[predM] =>
      // ???
      val predM: predM = m1.n
      val proof1: IsLessThan[m1.type, Succ[N]] = proof
      val proof2: IsLessThan[Succ[predM], Succ[N]] = proof1

      tail(predM)(using IsLessThan.reduction(using proof2))

The last line still cannot typecheck because what we want here is a IsLessThan[Succ[predM.type], Succ[N]], but what we have is IsLessThan[Succ[predM], Succ[N]]. (note that to allow the val proof2 line typecheck we have to make the first type parameter of IsLessThan covariant, since the widen type of m1.type is M & Succ[predM]).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Practical Refinement-Type Checking
Abstract. Refinement types allow many more properties of programs to be expressed and statically checked than conventional type systems.
Read more >
1 Refinement Types
Type refinement systems are conservative: they preserve the properties of the underlying type system. The framework to be presented as- sumes the existing...
Read more >
Request: allow refinement types · Issue #560 · python/mypy
Please consider allowing: Refine[C, f] to be used as a type, where C is a type and f is consistent with: C ->...
Read more >
Principles of Type Refinement (OPLSS 2016) - Noam Zeilberger
1.1 What is a type refinement system? Since type systems are so useful, it would be nice if we could say exactly what....
Read more >
Focusing on Liquid Refinement Typing - arXiv
ordinary recursive programs at all in our type refinements. ... constructing refined inductive values, pattern matching on refined inductive ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found