Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add tests for associated type multiple Effs and types #7555

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

jaschdoc
Copy link
Member

@jaschdoc jaschdoc commented Apr 8, 2024

  • Add traits
  • Add instance for Int32.
  • Add instance for String
  • Add instance for Vector[a]
  • Write polymorphic functions that use the trait.
  • Write monomorphic tests that exercise the trait directly and also the polymorphic functions.
  • Add tests

Related to #7424

@jaschdoc
Copy link
Member Author

jaschdoc commented Apr 8, 2024

@mlutze can you help me pinpoint the instance error? I really don't see how this is a valid instance error.

mod Test.Dec.Assoc.Type.Eff.Multiple {

    ////////////////////////////////////////////////////////
    // Type Definitions                                   //
    ////////////////////////////////////////////////////////

    eff Observe {
        pub def captureInt32(x: Int32): Unit
        pub def captureString(x: String): Unit
    }

    enum Split[e: Eff, a: Type] {
        case Nothing,
        case Value(a),
        case Pending(a -> Unit \ e, a)
    }

    trait Composable[a] {
        pub type E: Eff
        pub type B: Type -> Type
        pub type C: Eff -> Type -> Type
        pub def compose(f: a -> Unit \ Composable.E[a], x: a): Composable.C[a][Composable.E[a], Composable.B[a][a]]
        pub def reduce(x: Composable.C[a][Composable.E[a], Composable.B[a][a]]): Composable.B[a][a] \ Composable.E[a]
    }

    instance Composable[Vector[a]] with Composable[a] {
        pub type E = Composable.E[a]
        pub type B = Vector
        pub type C = Split

        pub def compose(f: Vector[a] -> Unit \ Composable.E[a], x: Vector[a]): Split[Composable.E[a], Vector[a]] =
            Split.Pending(f, x)

        pub def reduce(x: Split[Composable.E[a], Vector[a]]): Vector[a] \ Composable.E[a] = match x {
            case Split.Nothing       => Vector#{}
            case Split.Value(v)      => v
            case Split.Pending(f, v) => f(v); v
        }
    }
}
❌ -- Instance Error -------------------------------------------------- file://.../TestEffMultiple.flix


Mismatched signature 'compose' required by 'Composable'.

103 |         pub def compose(f: Vector[a] -> Unit \ Composable.E[a], x: Vector[a]): Split[Composable.E[a], Vector[a]] =
                      ^^^^^^^
                      mismatched signature.

Expected scheme: ∀(a). (Vector[a] -> Unit \ E[Vector[a]]) -> (Vector[a] -> C[Vector[a], E[Vector[a]], B[Vector[a], Vector[a]]]) with Test.Dec.Assoc.Type.Eff.Multiple.Composable[Vector[a]]
Actual scheme:   (Vector[a] -> Unit \ E[a]) -> (Vector[a] -> Split[E[a], Vector[a]]) with Test.Dec.Assoc.Type.Eff.Multiple.Composable[Vector[a]]

Explanation:
Tip: Modify the definition to match the signature.
❌ -- Instance Error -------------------------------------------------- file://.../TestEffMultiple.flix


Mismatched signature 'reduce' required by 'Composable'.

106 |         pub def reduce(x: Split[Composable.E[a], Vector[a]]): Vector[a] \ Composable.E[a] = match x {
                      ^^^^^^
                      mismatched signature.

Expected scheme: ∀(a). C[Vector[a], E[Vector[a]], B[Vector[a], Vector[a]]] -> B[Vector[a], Vector[a]] \ E[Vector[a]] with Test.Dec.Assoc.Type.Eff.Multiple.Composable[Vector[a]]
Actual scheme:   Split[E[a], Vector[a]] -> Vector[a] \ E[a] with Test.Dec.Assoc.Type.Eff.Multiple.Composable[Vector[a]]

Explanation:
Tip: Modify the definition to match the signature.

@mlutze
Copy link
Member

mlutze commented Apr 8, 2024

I think it is because of the Composable.B[a][a]. This substitutes to Composable.B[Vector[a], Vector[a]], which reduces to Vector[Vector[a]] but you just have Vector[a].

@jaschdoc
Copy link
Member Author

jaschdoc commented Apr 8, 2024

Ah thanks! :)

@jaschdoc
Copy link
Member Author

jaschdoc commented Apr 8, 2024

Okay so now it says that it is an irreducible associated type. Is it because of the recurrence of Vector when defining the instance for Vector? Not sure if this is also an error, but every instance in my program is now an irreducible associated type?

@mlutze
Copy link
Member

mlutze commented Apr 8, 2024

Okay so now it says that it is an irreducible associated type. Is it because of the recurrence of Vector when defining the instance for Vector? Not sure if this is also an error, but every instance in my program is now an irreducible associated type?

Irreducible shouldn't happen anymore, so it's probably a bug. Can you post the new program and the error message?

@jaschdoc
Copy link
Member Author

jaschdoc commented Apr 8, 2024

Ah I was on latest release rather than master :/

@magnus-madsen
Copy link
Member

@jaschdoc Is this blocked or OK?

@jaschdoc
Copy link
Member Author

@jaschdoc Is this blocked or OK?

No I don't believe so. Just haven't finished writing everything. I think I was reconsidering the design.

@jaschdoc
Copy link
Member Author

Error

    trait Transformable[a] {
        pub type E: Eff
        pub type B: Type
        pub def transform(x: a): Transformable.B[a] \ Transformable.E[a]
    }

    pub def transformAndCheckEq[b](eq: Transformable.B[a], x: a): Bool \ Transformable.E[a] with  Transformable[a], Eq[b] where Transformable.B[a] ~ b =
        Transformable.transform(x) == eq
#
# An unexpected error has been detected by the Flix compiler:
#
#   illegal type: B[Error]
#
# This is a bug in the Flix compiler. Please report it here:
#
# https://github.com/flix/flix/issues
#
# -- Flix Compiler --
#
# Flix Version : 0.46.0
#   incremental: All
#
# -- Java Virtual Machine --
#
# JVM Version  : 21.0.1 (2023-10-17)
# JVM Vendor   : GraalVM Community
# JAVA_HOME    : /home/_/.sdkman/candidates/java/21.0.1-graalce
# System       : Linux
#
# -- Stack Trace --
ca.uwaterloo.flix.util.InternalCompilerException: illegal type: B[Error]
	at ca.uwaterloo.flix.language.phase.Kinder$.$anonfun$checkAssocTypes$5(Kinder.scala:385)
	at ca.uwaterloo.flix.util.Validation$.$anonfun$fastTraverse$1(Validation.scala:284)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at ca.uwaterloo.flix.util.Validation$.fastTraverse(Validation.scala:283)
	at ca.uwaterloo.flix.util.Validation$.traverse(Validation.scala:237)
	at ca.uwaterloo.flix.util.Validation$.traverseX(Validation.scala:264)
	at ca.uwaterloo.flix.language.phase.Kinder$.checkAssocTypes(Kinder.scala:371)
	at ca.uwaterloo.flix.language.phase.Kinder$.$anonfun$visitSpec$5(Kinder.scala:343)
	at ca.uwaterloo.flix.util.Validation$.$anonfun$curry$10(Validation.scala:388)
	at ca.uwaterloo.flix.util.Validation$.ap(Validation.scala:337)
	at ca.uwaterloo.flix.util.Validation$.flatMapN(Validation.scala:569)
	at ca.uwaterloo.flix.language.phase.Kinder$.visitSpec(Kinder.scala:337)
	at ca.uwaterloo.flix.language.phase.Kinder$.$anonfun$visitDef$1(Kinder.scala:283)
	at ca.uwaterloo.flix.util.Validation$.flatMapN(Validation.scala:524)
	at ca.uwaterloo.flix.language.phase.Kinder$.visitDef(Kinder.scala:281)
	at ca.uwaterloo.flix.language.phase.Kinder$.$anonfun$visitDefs$1(Kinder.scala:268)
	at ca.uwaterloo.flix.util.ParOps$.$anonfun$parTraverseValues$1(ParOps.scala:106)
	at ca.uwaterloo.flix.util.ParOps$.$anonfun$parMap$2(ParOps.scala:64)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1423)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)

@jaschdoc
Copy link
Member Author

Error

    trait Composable[a] {
        pub type E: Eff
        pub type B: Type -> Type
        pub type C: Eff -> Type -> Type
        pub def compose(f: a -> Unit \ Composable.E[a], x: a): Composable.C[a][Composable.E[a], Composable.B[a][a]]
        pub def reduce(x: Composable.C[a][Composable.E[a], Composable.B[a][a]]): Composable.B[a][a] \ Composable.E[a]
    }
    pub def composeAndReduceEq[a: Type](eq: Composable.B[a][a], f: a -> Unit \ Composable.E[a], x: a): Bool \ Composable.E[a] with Composable[a], Eq[a] where Composable.B[a] ~ a =
        Composable.reduce(Composable.compose(f, x)) == eq
#
# An unexpected error has been detected by the Flix compiler:
#
#   Illegal kind: 'Type' of type 't879401'.
#
# This is a bug in the Flix compiler. Please report it here:
#
# https://github.com/flix/flix/issues
#
# -- Flix Compiler --
#
# Flix Version : 0.46.0
#   incremental: All
#
# -- Java Virtual Machine --
#
# JVM Version  : 21.0.1 (2023-10-17)
# JVM Vendor   : GraalVM Community
# JAVA_HOME    : /home/_/.sdkman/candidates/java/21.0.1-graalce
# System       : Linux
#
# -- Stack Trace --
ca.uwaterloo.flix.util.InternalCompilerException: Illegal kind: 'Type' of type 't879401'.
	at ca.uwaterloo.flix.language.ast.Type$Apply.kind$lzycompute(Type.scala:494)
	at ca.uwaterloo.flix.language.ast.Type$Apply.kind(Type.scala:491)
	at ca.uwaterloo.flix.language.phase.unification.Unification$.unifyTypes(Unification.scala:87)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.$anonfun$resolveTraitConstraint$4(ConstraintSolver.scala:468)
	at scala.collection.Iterator$$anon$9.next(Iterator.scala:584)
	at scala.collection.IterableOnceOps.collectFirst(IterableOnce.scala:1142)
	at scala.collection.IterableOnceOps.collectFirst$(IterableOnce.scala:1134)
	at scala.collection.AbstractIterator.collectFirst(Iterator.scala:1300)
	at ca.uwaterloo.flix.util.collection.ListOps$.findMap(ListOps.scala:38)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.$anonfun$resolveTraitConstraint$1(ConstraintSolver.scala:467)
	at ca.uwaterloo.flix.util.Result.flatMap(Result.scala:62)
	at ca.uwaterloo.flix.util.Result.flatMap$(Result.scala:61)
	at ca.uwaterloo.flix.util.Result$Ok.flatMap(Result.scala:94)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.resolveTraitConstraint(ConstraintSolver.scala:450)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.resolveOne(ConstraintSolver.scala:275)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.tryResolve$1(ConstraintSolver.scala:250)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.resolveOneOf(ConstraintSolver.scala:260)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.resolve(ConstraintSolver.scala:226)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.visitSpec(ConstraintSolver.scala:110)
	at ca.uwaterloo.flix.language.phase.typer.ConstraintSolver$.visitDef(ConstraintSolver.scala:56)
	at ca.uwaterloo.flix.language.phase.Typer$.visitDef(Typer.scala:177)
	at ca.uwaterloo.flix.language.phase.Typer$.$anonfun$visitDefs$2(Typer.scala:162)
	at ca.uwaterloo.flix.util.ParOps$.$anonfun$parTraverseValues$1(ParOps.scala:106)
	at ca.uwaterloo.flix.util.ParOps$.$anonfun$parMap$2(ParOps.scala:64)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1423)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)

// Polymorphic functions using Composable //
////////////////////////////////////////////////////////

pub def composeAndReduceEq(eq: Composable.B[a][a], f: a -> Unit \ Composable.E[a], x: a): Bool \ Composable.E[a] with Composable[a], Eq[a] where Composable.B[a][a] ~ a =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm stuck on this function. Not sure how to resolve this:

❌ -- Syntax Error -------------------------------------------------- file:///.../TestEffMultiple.flix

>> Illegal equality constraint.

126 |     pub def composeAndReduceEq(eq: Composable.B[a][a], f: a -> Unit \ Composable.E[a], x: a): Bool \ Composable.E[a] with Composable[a], Eq[a] where Composable.B[a][a] ~ a =
                                                                                                                                                           ^^^^^^^^^^^^^^^^^^^^^^
                                                                                                                                                           Equality constraints must have the form: `Assoc[var] ~ Type`.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The where clause can never be true. Imagine Composable.B[a] is defined as List. Then we are trying to unify List[a] ~ a which is impossible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is it impossible to do what I'm trying to achieve?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least for that constraint, yes.

Does this not work without the constraint?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need equality on the type C where C is the associated type of an instance for B which again is an associated type for an instance for A if that makes sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh noooooo that's a bug

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes me happy haha

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah wait

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ -- Syntax Error -------------------------------------------------- file:///.../TestEffMultiple.flix

>> Illegal equality constraint.

126 |     pub def composeAndReduceEq(eq: Composable.B[a][a], f: a -> Unit \ Composable.E[a], x: a): Bool \ Composable.E[a] with Composable[a], Eq[b] where Composable.B[a][a] ~ b =
                                                                                                                                                           ^^^^^^^^^^^^^^^^^^^^^^
                                                                                                                                                           Equality constraints must have the form: `Assoc[var] ~ Type`.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's a trickier problem. We can't currently do a constraint Eq[X[a]] if X is abstract. It's a design question. See https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Functor-Classes.html#t:Eq1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants