Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Nithingowda16 authored Mar 18, 2024
1 parent 642ee4f commit 9a43b3d
Show file tree
Hide file tree
Showing 17 changed files with 461 additions and 0 deletions.
1 change: 1 addition & 0 deletions SCALA/GITHUB/PROJECT/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.9.9
7 changes: 7 additions & 0 deletions SCALA/GITHUB/dependbot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "tuesday"
9 changes: 9 additions & 0 deletions SCALA/SRC/MAIN/SCALA/TEST/MYSUITE.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// For more information on writing tests, see
// https://scalameta.org/munit/docs/getting-started.html
class MySuite extends munit.FunSuite {
test("example test that succeeds") {
val obtained = 42
val expected = 42
assertEquals(obtained, expected)
}
}
10 changes: 10 additions & 0 deletions SCALA/SRC/MAIN/SCALA/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
lazy val root = project
.in(file("."))
.settings(
name := "scala3-example-project",
description := "Example sbt project that compiles using Scala 3",
version := "0.1.0",
scalaVersion := "3.3.3",
scalacOptions ++= Seq("-deprecation"),
libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test
)
40 changes: 40 additions & 0 deletions SCALA/SRC/MAIN/SCALA/contextfunctions.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try

/**
* Context Functions:
* - https://dotty.epfl.ch/docs/reference/contextual/context-functions.html
* - https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html
*/
object ContextFunctions:

object context:
// type alias Contextual
type Contextual[T] = ExecutionContext ?=> T

// sum is expanded to sum(x, y)(ctx)
def asyncSum(x: Int, y: Int): Contextual[Future[Int]] = Future(x + y)

def asyncMult(x: Int, y: Int)(using ctx: ExecutionContext) = Future(x * y)

object parse:

type Parseable[T] = GivenInstances.StringParser[T] ?=> Try[T]

def sumStrings(x: String, y: String): Parseable[Int] =
val parser = summon[GivenInstances.StringParser[Int]]
val tryA = parser.parse(x)
val tryB = parser.parse(y)

for
a <- tryA
b <- tryB
yield a + b

def test(): Unit =
import ExecutionContext.Implicits.global
context.asyncSum(3, 4).foreach(println)
context.asyncMult(3, 4).foreach(println)

println(parse.sumStrings("3", "4"))
println(parse.sumStrings("3", "a"))
34 changes: 34 additions & 0 deletions SCALA/SRC/MAIN/SCALA/conversion.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import scala.language.implicitConversions

/**
* Conversions: https://dotty.epfl.ch/docs/reference/contextual/conversions.html
*/
object Conversion:

case class IntWrapper(a: Int) extends AnyVal
case class DoubleWrapper(b: Double) extends AnyVal

def convert[T, U](x: T)(using converter: Conversion[T, U]): U = converter(x)

given IntWrapperToDoubleWrapper: Conversion[IntWrapper, DoubleWrapper] = new Conversion[IntWrapper, DoubleWrapper] {
override def apply(i: IntWrapper): DoubleWrapper = DoubleWrapper(i.a.toDouble)
}
// Or:
// given IntWrapperToDoubleWrapper: Conversion[IntWrapper, DoubleWrapper] =
// (i: IntWrapper) => DoubleWrapper(i.a.toDouble)

def useConversion(using f: Conversion[IntWrapper, DoubleWrapper]) =
val y: IntWrapper = IntWrapper(4)
val x: DoubleWrapper = y
x

/* Not working anymore.
def useConversion(implicit f: A => B) = {
val y: A = ...
val x: B = a // error under Scala 3
}
*/

def test(): Unit =
println(useConversion)
println(convert(IntWrapper(42)))
39 changes: 39 additions & 0 deletions SCALA/SRC/MAIN/SCALA/enumtypes.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Enum Types: https://dotty.epfl.ch/docs/reference/enums/adts.html
*/
object EnumTypes:

enum ListEnum[+A]:
case Cons(h: A, t: ListEnum[A])
case Empty


enum Planet(mass: Double, radius: Double):
private final val G = 6.67300E-11
def surfaceGravity = G * mass / (radius * radius)
def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity

case Mercury extends Planet(3.303e+23, 2.4397e6)
case Venus extends Planet(4.869e+24, 6.0518e6)
case Earth extends Planet(5.976e+24, 6.37814e6)
case Mars extends Planet(6.421e+23, 3.3972e6)
case Jupiter extends Planet(1.9e+27, 7.1492e7)
case Saturn extends Planet(5.688e+26, 6.0268e7)
case Uranus extends Planet(8.686e+25, 2.5559e7)
case Neptune extends Planet(1.024e+26, 2.4746e7)
end Planet

def test(): Unit =
val emptyList = ListEnum.Empty
val list = ListEnum.Cons(1, ListEnum.Cons(2, ListEnum.Cons(3, ListEnum.Empty)))
println("Example 1: \n"+emptyList)
println(s"${list}\n")

def calculateEarthWeightOnPlanets(earthWeight: Double) =
val mass = earthWeight/Planet.Earth.surfaceGravity
for p <- Planet.values do
println(s"Your weight on $p is ${p.surfaceWeight(mass)}")

println("Example 2:")
calculateEarthWeightOnPlanets(80)
end test
32 changes: 32 additions & 0 deletions SCALA/SRC/MAIN/SCALA/giveinstances.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import scala.util.{Success, Try}

/**
* Implied Instances: https://dotty.epfl.ch/docs/reference/contextual/givens.html
*/
object GivenInstances:

sealed trait StringParser[A]:
def parse(s: String): Try[A]

object StringParser:

def apply[A](using parser: StringParser[A]): StringParser[A] = parser

private def baseParser[A](f: String => Try[A]): StringParser[A] = new StringParser[A] {
override def parse(s: String): Try[A] = f(s)
}

given stringParser: StringParser[String] = baseParser(Success(_))
given intParser: StringParser[Int] = baseParser(s => Try(s.toInt))

given optionParser[A](using parser: => StringParser[A]): StringParser[Option[A]] = new StringParser[Option[A]] {
override def parse(s: String): Try[Option[A]] = s match
case "" => Success(None) // implicit parser not used.
case str => parser.parse(str).map(x => Some(x)) // implicit parser is evaluated at here
}

def test(): Unit =
println(summon[StringParser[Option[Int]]].parse("21"))
println(summon[StringParser[Option[Int]]].parse(""))
println(summon[StringParser[Option[Int]]].parse("21a"))
println(summon[StringParser[Option[Int]]](using StringParser.optionParser[Int]).parse("42"))
26 changes: 26 additions & 0 deletions SCALA/SRC/MAIN/SCALA/intersection.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Intersection Types: https://dotty.epfl.ch/docs/reference/new-types/intersection-types.html
*/
object IntersectionTypes:

sealed trait X:
def x: Double
def tpe: X

sealed trait Y:
def y: Double
def tpe: Y

type P = Y & X
type PP = X & Y

final case class Point(x: Double, y: Double) extends X with Y:
override def tpe: X & Y = ???

def test(): Unit =
def euclideanDistance(p1: X & Y, p2: X & Y) =
Math.sqrt(Math.pow(p2.y - p1.y, 2) + Math.pow(p2.x - p1.x, 2))

val p1: P = Point(3, 4)
val p2: PP = Point(6, 8)
println(euclideanDistance(p1, p2))
31 changes: 31 additions & 0 deletions SCALA/SRC/MAIN/SCALA/main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@main
def Main(args: String*): Unit =
runExample("Trait Params")(TraitParams.test())

runExample("Enum Types")(EnumTypes.test())

runExample("Context Functions")(ContextFunctions.test())

runExample("Given Instances")(GivenInstances.test())

runExample("Conversion")(Conversion.test())

runExample("Union Types")(UnionTypes.test())

runExample("Intersection Types")(IntersectionTypes.test())

runExample("Type Lambda")(TypeLambdas.test())

runExample("Multiversal Equality")(MultiversalEquality.test())

runExample("Parameter Untupling")(ParameterUntupling.test())

runExample("Structural Types")(StructuralTypes.test())

runExample("Pattern Matching")(PatternMatching.test())
end Main

private def runExample(name: String)(f: => Unit): Unit =
println(Console.MAGENTA + s"$name example:" + Console.RESET)
f
println()
35 changes: 35 additions & 0 deletions SCALA/SRC/MAIN/SCALA/multiversal.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import scala.language.strictEquality

/**
* Multiversal Equality: https://dotty.epfl.ch/docs/reference/contextual/multiversal-equality.html
* scala.CanEqual definition: https://github.com/lampepfl/dotty/blob/master/library/src/scala/CanEqual.scala
*/
object MultiversalEquality:

def test(): Unit =
// Values of types Int and String cannot be compared with == or !=,
// unless we add the derived delegate instance like:
given CanEqual[Int, String] = CanEqual.derived
println(3 == "3")

// By default, all numbers are comparable, because of;
// given canEqualNumber as CanEqual[Number, Number] = derived
println(3 == 5.1)

// By default, all Sequences are comparable, because of;
// given canEqualSeq[T, U](using eq: CanEqual[T, U]) as CanEqual[Seq[T], Seq[U]] = derived
println(List(1, 2) == Vector(1, 2))

class A(a: Int)
class B(b: Int)

val a = A(4)
val b = B(4)

// scala.language.strictEquality is enabled, therefore we need some extra delegate instances
// to compare instances of A and B.
given CanEqual[A, B] = CanEqual.derived
given CanEqual[B, A] = CanEqual.derived

println(a != b)
println(b == a)
15 changes: 15 additions & 0 deletions SCALA/SRC/MAIN/SCALA/parameteruntupling.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Parameter Untupling: https://dotty.epfl.ch/docs/reference/other-new-features/parameter-untupling.html
*/
object ParameterUntupling:

def test(): Unit =
val xs: List[String] = List("d", "o", "t", "t", "y")

/**
* Current behaviour in Scala 2.12.2 :
* error: missing parameter type
* Note: The expected type requires a one-argument function accepting a 2-Tuple.
* Consider a pattern matching anonymous function, `{ case (s, i) => ... }`
*/
xs.zipWithIndex.map((s, i) => println(s"$i: $s"))
83 changes: 83 additions & 0 deletions SCALA/SRC/MAIN/SCALA/patternmatching.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Pattern Matching: https://dotty.epfl.ch/docs/reference/changed-features/pattern-matching.html
*/
object PatternMatching:

object booleanPattern:

object Even:
def unapply(s: String): Boolean = s.length % 2 == 0


object productPattern:

class Person(name: String, age: Int) extends Product:
// if we not define that, it will give compile error.
// we change the order
def _1 = age
def _2 = name

// Not used by pattern matching: Product is only used as a marker trait.
def canEqual(that: Any): Boolean = ???
def productArity: Int = ???
def productElement(n: Int): Any = ???

object Person:
def unapply(a: (String, Int)): Person = Person(a._1, a._2)


object seqPattern:

// adapted from https://danielwestheide.com/blog/the-neophytes-guide-to-scala-part-2-extracting-sequences/
object Names:
def unapplySeq(name: String): Option[Seq[String]] =
val names = name.trim.split(" ")
if names.size < 2 then None
else Some(names.last :: names.head :: names.drop(1).dropRight(1).toList)


object namePattern:

class Name(val name: String):
def get: String = name
def isEmpty = name.isEmpty

object Name:
def unapply(s: String): Name = Name(s)


def test(): Unit =
import booleanPattern.*

"even" match
case s @ Even() => println(s"$s has an even number of characters")
case s => println(s"$s has an odd number of characters")

// https://dotty.epfl.ch/docs/reference/changed-features/vararg-splices.html
def containsConsecutive(list: List[Int]): Boolean = list match
case List(a, b, xs*) => a == b || containsConsecutive(b :: xs.toList)
case Nil | List(_, _*) => false

println(containsConsecutive(List(1, 2, 3, 4, 5)))
println(containsConsecutive(List(1, 2, 3, 3, 5)))

import productPattern.*
("john", 42) match
case Person(n, a) => println(s"name: $n, age: $a")

import seqPattern.*

def greet(fullName: String) = fullName match
case Names(lastName, firstName, _*) => "Good morning, " + firstName + " " + lastName + "!"
case _ => "Welcome! Please make sure to fill in your name!"

println(greet("Alan Turing"))
println(greet("john"))
println(greet("Wolfgang Amadeus Mozart"))

import namePattern.*
"alice" match
case Name(n) => println(s"name is $n")
case _ => println("empty name")

end PatternMatching
Loading

0 comments on commit 9a43b3d

Please sign in to comment.