-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Abhijit Sarkar
committed
Dec 18, 2024
1 parent
c5ce581
commit a39c8b7
Showing
61 changed files
with
285 additions
and
1,785 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,20 @@ | ||
# macOS | ||
.DS_Store | ||
*.class | ||
*.log | ||
*~ | ||
|
||
# sbt | ||
dist/* | ||
target/ | ||
lib_managed/ | ||
src_managed/ | ||
project/boot/ | ||
project/project | ||
project/plugins/project/ | ||
project/local-plugins.sbt | ||
.history | ||
.ensime | ||
.ensime_cache/ | ||
.sbt-scripted/ | ||
local.sbt | ||
# idea | ||
.idea | ||
.idea_modules | ||
/.worksheet/ | ||
|
||
# Bloop | ||
.bsp | ||
# mill | ||
out/ | ||
|
||
# VS Code | ||
.bsp/ | ||
.metals/ | ||
.vscode/ | ||
|
||
# Metals | ||
.bloop/ | ||
.metals/ | ||
metals.sbt | ||
|
||
# IDEA | ||
.idea | ||
.idea_modules | ||
/.worksheet/ | ||
# virtual machine crash logs | ||
hs_err_pid* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
0.12.3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
version = "3.7.17" | ||
version = "3.8.3" | ||
align.preset = more | ||
maxColumn = 120 | ||
runner.dialect = scala3 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package build | ||
|
||
import mill._, scalalib._, scalafmt._ | ||
import $packages._ | ||
import $file.{versions => v} | ||
|
||
def isBookChapter(p: os.Path) = os.isDir(p) && "ch\\d{2}".r.matches(p.baseName) | ||
|
||
def moduleNames = interp.watchValue( | ||
os.walk(millSourcePath, !isBookChapter(_), maxDepth = 1) | ||
.map(_.last) | ||
) | ||
|
||
object modules extends Cross[CatsModule](moduleNames) | ||
|
||
trait CatsModule extends ScalaModule with Cross.Module[String] with ScalafmtModule { | ||
|
||
val scalaVersion = v.scalaVersion | ||
|
||
// Ends with 'modules' that need to be removed | ||
def millSourcePath = super.millSourcePath / os.up / crossValue | ||
|
||
def scalacOptions: T[Seq[String]] = Seq( | ||
"-encoding", "UTF-8", | ||
"-feature", | ||
"-Werror", | ||
"-explain", | ||
"-deprecation", | ||
"-unchecked", | ||
"-Wunused:all", | ||
"-rewrite", | ||
"-indent", | ||
"-source", "future", | ||
) | ||
|
||
object test extends ScalaTests with TestModule.ScalaTest { | ||
val commonDeps = Seq( | ||
ivy"org.scalatest::scalatest:${v.scalatestVersion}", | ||
ivy"org.scalatestplus::scalacheck-1-18:${v.scalacheckVersion}" | ||
) | ||
|
||
def ivyDeps = Task{commonDeps} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package ch02 | ||
|
||
/* | ||
Structural corecursion works by considering all the possible outputs, which are the constructors of | ||
the algebraic data type, and then working out the conditions under which we’d call each constructor. | ||
We could abstract structural corecursion as an unfold. | ||
*/ | ||
enum MyList[A]: | ||
case Empty() | ||
case Pair(_head: A, _tail: MyList[A]) | ||
|
||
def map[B](f: A => B): MyList[B] = | ||
// this match | ||
// case Empty() => Empty() | ||
// case Pair(head, tail) => Pair(f(head), tail.map(f)) | ||
MyList.unfold(this)(_.isEmpty, a => f(a.head), _.tail) | ||
|
||
def isEmpty: Boolean = | ||
this match | ||
case Empty() => true | ||
case _ => false | ||
|
||
def head: A = | ||
this match | ||
case Pair(head, _) => head | ||
case _ => scala.sys.error("empty list") | ||
|
||
def tail: MyList[A] = | ||
this match | ||
case Pair(_, tail) => tail | ||
case _ => scala.sys.error("empty list") | ||
|
||
def fold[B](zero: B)(f: (A, B) => B): B = | ||
this match | ||
case Empty() => zero | ||
case Pair(head, tail) => f(head, tail.fold(zero)(f)) | ||
|
||
def toSeq: Seq[A] = fold(Seq.empty)(_ +: _) | ||
|
||
object MyList: | ||
/* | ||
Types inferred for one method parameter cannot be used for other method parameters in the same parameter list. | ||
However, types inferred for one method parameter list can be used in subsequent lists. | ||
*/ | ||
def unfold[A, B](seed: A)(stop: A => Boolean, f: A => B, next: A => A): MyList[B] = | ||
if stop(seed) then MyList.Empty() | ||
else MyList.Pair(f(seed), unfold(next(seed))(stop, f, next)) | ||
|
||
def fill[A](n: Int)(elem: => A): MyList[A] = | ||
unfold(0)(_ == n, _ => elem, _ + 1) | ||
|
||
def iterate[A](start: A, len: Int)(f: A => A): MyList[A] = | ||
unfold((0, start))(_._1 == len, _._2, (i, a) => (i + 1, f(a))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package ch02 | ||
|
||
/* | ||
Structural recursion works by considering all the possible inputs (which we usually represent as patterns), | ||
and then working out what we do with each input case. | ||
We could abstract structural recursion as an fold. | ||
*/ | ||
enum Tree[A]: | ||
case Leaf(value: A) | ||
case Node(left: Tree[A], right: Tree[A]) | ||
|
||
/** @return | ||
* the number of values (Leafs) stored in the Tree | ||
*/ | ||
def size: Int = this.fold(_ => 1, _ + _) | ||
// this match | ||
// case Tree.Leaf(value) => 1 | ||
// case Tree.Node(left, right) => left.size + right.size | ||
|
||
/** @param elem | ||
* element to look for | ||
* @return | ||
* true if the Tree contains a given element of type A, and false otherwise | ||
*/ | ||
def contains(elem: A): Boolean = this.fold(_ == elem, _ || _) | ||
// this match | ||
// case Tree.Leaf(value) => value == elem | ||
// case Tree.Node(left, right) => left.contains(elem) || right.contains(elem) | ||
|
||
/** @param f | ||
* value transformation function | ||
* @return | ||
* a Tree[B] given a function A => B | ||
*/ | ||
def map[B](f: A => B): Tree[B] = this.fold(v => Tree.Leaf(f(v)), (l, r) => Tree.Node(l, r)) | ||
// this match | ||
// case Tree.Leaf(value) => Tree.Leaf(f(value)) | ||
// case Tree.Node(left, right) => Tree.Node(left.map(f), right.map(f)) | ||
|
||
def fold[B](f: (A => B), g: (B, B) => B): B = | ||
this match | ||
case Tree.Node(left, right) => g(left.fold(f, g), right.fold(f, g)) | ||
case Tree.Leaf(value) => f(value) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package ch02 | ||
|
||
import org.scalatest.funspec.AnyFunSpec | ||
import org.scalatest.matchers.should.Matchers.shouldBe | ||
|
||
class MyListSpec extends AnyFunSpec: | ||
describe("fill"): | ||
it("stateless"): | ||
val actual = MyList.fill(5)(1) | ||
actual.toSeq shouldBe Seq.fill(5)(1) | ||
|
||
it("stateful"): | ||
var counter = 0 | ||
|
||
def getAndInc(): Int = | ||
val temp = counter | ||
counter = counter + 1 | ||
temp | ||
|
||
val actual = MyList.fill(5)(getAndInc()) | ||
actual.toSeq shouldBe (0 to 4) | ||
counter shouldBe 5 | ||
|
||
describe("iterate"): | ||
it("decrement"): | ||
val actual = MyList.iterate(0, 5)(_ - 1) | ||
actual.toSeq shouldBe (0 to -4 by -1) | ||
|
||
describe("map"): | ||
it("evens"): | ||
val actual = MyList.iterate(0, 5)(_ + 1).map(_ * 2) | ||
actual.toSeq shouldBe (0 to 8 by 2) | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
Oops, something went wrong.