Skip to content

Instantly share code, notes, and snippets.

@nzpr
Last active August 24, 2023 07:58
Show Gist options
  • Save nzpr/5ff4909d07487b2291f4003cac0f358d to your computer and use it in GitHub Desktop.
Save nzpr/5ff4909d07487b2291f4003cac0f358d to your computer and use it in GitHub Desktop.
import cats.Alternative
import cats.kernel.Semigroup
import cats.syntax.all._
// Concrete structure, deep embedding (initial encoding).
// Represents something like a dictionary or key-value store.
type MyStruct = List[(String, Int)]
val myStruct: MyStruct = List(("a", 1), ("b", 2), ("c", 3))
// This are not desugared list constructors but operations on List. But ok, looks similar.
val myStruct: MyStruct = ("a", 1) +: ("b", 2) +: ("c", 3) +: List()
// First abstraction, product constructor is abstracted and supplied
// to the function, List is still concrete.
type KV1[A] = (String, Integer) => A => List[A]
// Bad thing there is no way to say (String => Integer) instead of (String, Integer), (,) is not a function
def kv1[A](f: (String, Integer) => A) = List(f("a", 1), f("b", 2), f("c", 3))
// -- To get concrete structure apply "abstract definition" to product constructor.
type MyStruct1 = List[(String, Integer)]
val myStruct1 = kv1(_ -> _) // no (,) in Scala but there is -> for a tuple
// List Cons constructor (:) can be replaced with compose function (.) and empty
// list will be supplied later when constructing concrete value.
// (.) :: (b -> c) -> (a -> b) -> a -> c
// kv1a :: (String -> Integer -> a -> a) -> a -> a
// kv1a f = f "a" 1
// . f "b"
// . f "c" 3
// TODO Q1.
// that's odd f("a", 1) type is (A, A) why this is function composition?
type KV1A[A] = (String, Integer) => (A, A) => (A, A)
def kv1a[A](f: (String, Integer) => (A, A)) = f("a", 1) andThen f("b", 2) andThen f("c", 3)
def kv1a[A]: KV1A[A] = (f:(String, Integer) => (A, A)) => f("a", 1) andThen f("b", 2) andThen f("c", 3)
// -- Composition can also be a Semigroup `mappend`(<>)(Monoid is Semigroup with Unit).
// --(<>) implementation for List is concat(++)
// -- http: //hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#line-290
type KV1B[A] = Semigroup[A] => (String, Integer) => A => A
// TODO Q2
// ok so I used |+| from cats.Semigroup instead of (.) but that's not a function composition
// kv1b returns here value (A) and not a function
def kv1b[A: Semigroup](f: (String, Integer) => A) = f("a", 1) |+| f("b", 2) |+| f("c", 3)
// -- Composition with Alternative - an associative binary operation.
type KV1C[F[_], A] = Alternative[F] => (String, Integer) => F[A] => F[A]
// TODO Q3
// so here return type is as well F[A] not KV1C[F, A]. How to make kv1C return a function KV1C[F, A]?
def kv1C[F[_]: Alternative, A](f: (String, Integer) => F[A]): KV1C[F, A] = f("a", 1) <+> f("b", 2) <+> f("c", 3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment