Last active
August 24, 2023 07:58
-
-
Save nzpr/5ff4909d07487b2291f4003cac0f358d to your computer and use it in GitHub Desktop.
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
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