Here's an ADT which is not a GADT, in Haskell:
data Expr = IntExpr Int | BoolExpr Bool| // (.) :: (b -> c) -> (a -> b) -> a -> c | |
| implicit class FancyComposition[A, B, C](f: B => C) { | |
| def `.`(g: A => B): A => C = f.compose(g) | |
| } | |
| val f: Int => String = _.toString | |
| val g: String => Boolean = _.contains("1") | |
| val h: Int => Boolean = g `.` f |
| import cats.Traverse | |
| import cats.effect._ | |
| import cats.effect.concurrent.Semaphore | |
| import cats.temp.par._ | |
| import cats.syntax.all._ | |
| import scala.concurrent.duration._ | |
| object Main extends IOApp { | |
| import ParTask._ |
| import cats.data.Kleisli | |
| import cats.effect.{ Concurrent, Sync } | |
| import cats.effect.concurrent.MVar | |
| import cats.implicits._ | |
| import cats.{ Applicative, Functor, Monad } | |
| // Let's start with our dsl | |
| // First we need to interact with a console | |
| trait Console[F[_]] { |
| package quantified | |
| import cats.Monad | |
| import scala.language.implicitConversions | |
| /** C[_] constraint applied to type F[_, _] quantified in first parameter */ | |
| final class Quant[+C[_[_]], F[_, _]] private (private val erased: C[F[Any, ?]]) extends AnyVal { | |
| type State = Defined |
| import cats.effect._ | |
| import cats.syntax.functor._ | |
| import fs2._ | |
| import java.nio.file.Paths | |
| import java.util.concurrent.Executors | |
| import scala.concurrent.ExecutionContext | |
| import scala.util.Try | |
| object CsvApp extends IOApp { |
| import cats.Id | |
| import polymorphic._ | |
| import polymorphic.syntax.all._ | |
| // Type mismatch: found b.type, required: A | |
| //def nope[A, B](f: A => List[A], b: B, s: String): (List[B], List[String]) = (f(b), f(s)) | |
| // If Scala had Rank-N types it would be defined as: | |
| //def notValid[B](f: (A => List[A]) forAll { A }, b: B, s: String): (List[B], List[String]) = (f(b), f(s)) |
| import polymorphic._ | |
| import polymorphic.syntax.all._ | |
| class Data[A](val x: A, val f: A => String) | |
| trait E { | |
| def f(ex: ∃[Data]): String = ex match { case Exists(d) => d.f(d.x) } | |
| } | |
| val e = new E {} |