Skip to content

Instantly share code, notes, and snippets.

@milessabin
Created August 29, 2019 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milessabin/5005f81aebd50ce3faf93e8fa61a3f5f to your computer and use it in GitHub Desktop.
Save milessabin/5005f81aebd50ce3faf93e8fa61a3f5f to your computer and use it in GitHub Desktop.
/*
* Copyright (c) 2019 Miles Sabin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package shapeless
import scala.compiletime._
object ops2 {
type FoldLeft[T <: Tuple, B, A <: B, Step[_ <: B, _] <: B] = T match {
case Unit => A
case h *: t => FoldLeft[t, B, Step[A, h], Step]
}
type Reverse[T <: Tuple] = FoldLeft[T, Tuple, Unit, [A <: Tuple, E] =>> (E *: A)]
type Length[T <: Tuple] = FoldLeft[T, Int, 0, [A <: Int, E] =>> S[A]]
type IndexOf[T <: Tuple, U] <: Int = T match {
case h *: t =>
h match {
case U => 0
case _ => S[IndexOf[t, U]]
}
}
type Unwrap[F[_]] =
[FA] =>> FA match {
case F[a] => a
}
class Inv[T]
type Eql[A] = [B] =>> Inv[B] match {
case Inv[A] => true
case _ => false
}
type Sub[A] = [B] =>> B match {
case A => true
case _ => false
}
type Not[F[_]] = [T] =>> F[T] match {
case true => false
case false => true
}
type Or[F[_], G[_]] = [T] =>> F[T] match {
case true => true
case false => G[T]
}
type And[F[_], G[_]] = [T] =>> F[T] match {
case true => G[T]
case false => false
}
type Mapped[T <: Tuple, F[_]] <: Tuple = T match {
case Unit => Unit
case h *: t => F[h] *: Mapped[t, F]
}
type Comapped[T <: Tuple, F[_]] = Mapped[T, Unwrap[F]]
type Filter[T <: Tuple, F[_] <: Boolean] <: Tuple = T match {
case Unit => Unit
case h *: t =>
F[h] match {
case true => h *: Filter[t, F]
case false => Filter[t, F]
}
}
enum Fruit {
case Apple()
case Pear()
case Banana()
}
import Fruit._
the[Reverse[(Int, String, Boolean)] =:= (Boolean, String, Int)]
the[Length[(Int, String, Boolean)] =:= 3]
the[IndexOf[(Int, String, Boolean), Boolean] =:= 2]
the[Mapped[(Int, String, Boolean), Option] =:= (Option[Int], Option[String], Option[Boolean])]
the[Comapped[(Option[Int], Option[String], Option[Boolean]), Option] =:= (Int, String, Boolean)]
the[Filter[(Apple, Pear, Banana, Pear), Eql[Pear]] =:= (Pear, Pear)]
the[Filter[(Apple, Pear, Banana, Pear), Eql[Fruit]] =:= Unit]
the[Filter[(Apple, Int, Banana, String), Sub[Fruit]] =:= (Apple, Banana)]
the[Filter[(Apple, Int, Banana, String), Not[Sub[Fruit]]] =:= (Int, String)]
the[Filter[(Apple, Pear, Banana, Pear), Or[Eql[Apple], Eql[Banana]]] =:= (Apple, Banana)]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment