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.

Type check for polymorphic function types

See original GitHub issue

Compiler version

3.1.2-RC1-bin-20211102-82172ed-NIGHTLY

Minimized code

I’ve found it really hard to minimize this due too all the moving components. You can click the little triangle to see the full attempt.

Here are the bits where I think it goes wrong:

// a generated group of tests for type V
// reduced from a collection of these
val condUpperBoundPartialOrdering: [V] => () => TestGroup[V]

// a function that check if a group of tests applies to a specific object
// inline here is necessary for it to work (the positive case)
inline def appliesTo[V](tl: TestLattice[_, V], v: TestGroup[V]): Boolean

// applying the test check to an object
// reduced form a "reduce"
def app[X, Y](x: X, f: X => Y): Y
// Necesarry abstract definitions
trait JoinLattice[A] extends PartialOrdering[A]:
  override def tryCompare(x: A, y: A): Option[0 | 1 | -1] = ???
  override def lteq(x: A, y: A): Boolean = ???

trait UpperBound[A]
trait LowerBound[A]
trait Finite[A]:
  val elements: Set[A]

trait Atomic[A] extends LowerBound[A]
trait CoAtomic[A] extends UpperBound[A]

trait BoundedJoinLattice[A] extends JoinLattice[A] with LowerBound[A]
trait DoubleBoundedJoinLattice[A] extends BoundedJoinLattice[A] with UpperBound[A]
trait AtomicJoinLattice[A] extends BoundedJoinLattice[A] with Atomic[A]
trait BoundedCoAtomicJoinLattice[A] extends BoundedJoinLattice[A] with CoAtomic[A]
trait DoubleAtomicJoinLattice[A] extends BoundedCoAtomicJoinLattice[A] with AtomicJoinLattice[A]

trait FiniteDoubleAtomicJoinLattice[A] extends DoubleAtomicJoinLattice[A] with Finite[A]

// Necesarry concrete definitions
def optionsLattice[A](options: Seq[A]) = new FiniteDoubleAtomicJoinLattice[Set[A]]:
  val elements = options.toSet.subsets.toSet

def evidenceLattice[A] = new BoundedJoinLattice[(Set[A], Set[A])] {}

// Test utils
abstract class TestGroup[V]:
  type R
  val group: String

case class TestLattice[R, V](val name: String, lattice: R, elements: Iterable[V]):
  type Lattice = R
  type Carrier = V

object TestLattice:
  def fromFinite[R <: Finite[V], V](name: String, lattice: R) =
    TestLattice(name, lattice, lattice.elements)

// Util for example
def app[X, Y](x: X, f: X => Y) = f(x)

inline def appliesTo[V](tl: TestLattice[_, V], v: TestGroup[V]) =
  tl.lattice match
    case q: v.R => println(("matches", v, q))
    case q => println(("misses", v, q))

// Values for example
val to_test = Seq(
  TestLattice("Evidence (Set, Set)", evidenceLattice[Int], {
    val range = (0 to 3).toSet.subsets.toSet
    for x <- range; y <- range yield (x, y)
  }),
  TestLattice.fromFinite("Options (Set)", optionsLattice(1 to 4))
)

val condUpperBoundPartialOrdering = [V] => () => new TestGroup[V]:
  type R = UpperBound[V] & PartialOrdering[V]
  val group = "UpperBound PartialOrdering laws"

@main def example =
  for ins <- to_test do
    // this works correctly
    app(condUpperBoundPartialOrdering[ins.Carrier](), v => appliesTo(ins, v))
    // this does not compile
//    app(condUpperBoundPartialOrdering, v => appliesTo(ins, v[ins.Carrier]()))

Output

[error]    |      app(condUpperBoundPartialOrdering, v => appliesTo(ins, v[ins.Carrier]()))
[error]    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |Found:    ([V] => () => TestGroup[V]{R = IP.lib.UpperBound[V] & PartialOrdering[V]}) => 
[error]    |  Unit
[error]    |Required: ([V] => () => TestGroup[Any]{R = IP.lib.UpperBound[Any] & PartialOrdering[Any]}) =>
[error]    |  Unit

Expectation

Work the same as

app(condUpperBoundPartialOrdering[ins.Carrier](), v => appliesTo(ins, v))

Two things here:

  • I kinda expect ([V] => () => TestGroup[V]{R = IP.lib.UpperBound[V] & PartialOrdering[V]}) to match type ([V] => () => TestGroup[Any]{R = IP.lib.UpperBound[Any] & PartialOrdering[Any]})?
  • I expect (λx.G) (f v) to be equivalent to (λx.G[x := (f x)]) v.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
KacperFKorbancommented, Nov 10, 2021
  1. Could you fill in the compiler version?
  2. Could you also paste a complete snippet you’re running?
0reactions
bishaboshacommented, Nov 12, 2021

What you are doing in this example relies on static types to work, so I can only to suggest that you zip each Cond with a test when you construct the Seq

Read more comments on GitHub >

github_iconTop Results From Across the Web

Polymorphic Function Types - Scala 3
A polymorphic function type is a function type which accepts type parameters. ... Here is how to implement this using polymorphic function types:....
Read more >
Polymorphic Function Types
This type describes function values which take a type A as a parameter, then take a list of type List[A] , and return...
Read more >
Type polymorphic functions in TypeScript - Zhenghao
Type polymorphic functions in TypeScript · The argument str has the string union type "int" | "char" , and to make the return...
Read more >
Basic Polymorphic Typechecking - Luca Cardelli
Parametric polymorphic type systems share with Algol 68 properties of compile-time checking, static typing and treatment of higher-order functions, ...
Read more >
Handout 6: Polymorphic Type Systems
Polymorphic functions. A function that can take arguments of different types or return results of different types, is called a polymorphic function.
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