Какова цель `F [Something [F]]`? - PullRequest
3 голосов
/ 03 апреля 2020

Я вижу много F[Request[F]], F[Monitor[F]] и F[Something[F]] вокруг. Хотя я понимаю механику того, как справиться с этим, у меня нет интуитивного понимания того, почему какой-то эффект (F) должен выглядеть так (как обертывающий вокруг Something, так и появляющийся внутри этого Something). Insights?

Ответы [ 2 ]

3 голосов
/ 03 апреля 2020

Простой HTTP-сервер может быть представлен следующей функцией: Запрос => Ответ

Однако нам обычно требуется выполнить эффективную операцию, такую ​​как получение данных из базы данных или вызов внешней службы. Такие случаи мы определяем так: Request => F [Response]

http4s имеет собственную абстракцию над маршрутами (конечными точками), называемой HttpRoutes [F], и это псевдоним типа для Kleisli [OptionT [F,?], Request, Response], как упомянуто в документации.

Как мы знаем из документации котов, Kleisli - это просто композиции функций, которые возвращают значение monadi c, например Option [A], Either [L, R], et c.

Одним из наиболее полезных свойств функций является их составление. То есть, учитывая функцию A => B и функцию B => C, мы можем объединить их, чтобы создать новую функцию A => C.

В этом случае Kleislei http4s принимает запрос и возвращает F [ответ], просто запрос => F [ответ]. F - это тип эффекта.

С небольшим изменением указанных выше типов запросов и ответов мы получаем следующее:

type HttpRoutes[F] = Kleisli[OptionT[F, *], Request[F], Response[F]]

HttpRoutes [F] объявляется как простая серия тематические заявления. Каждый оператор case пытается сопоставить и при необходимости извлечь из входящего запроса [F]. Код, связанный с первым совпадающим регистром, используется для генерации F [Response [F]].

Простейший оператор case совпадает со всеми запросами, ничего не извлекая. Правая часть запроса должна возвращать F [Ответ [F]].

Здесь мы видим простую демонстрацию F [Ответ [F]]

scala> val getRoot = Request[IO](Method.GET, uri"/")
getRoot: org.http4s.Request[cats.effect.IO] = Request(method=GET, uri=/, headers=Headers())

scala> val io = service.orNotFound.run(getRoot)
io: cats.effect.IO[org.http4s.Response[cats.effect.IO]] = <function1>

Здесь cats.effect.IO[org.http4s.Response[cats.effect.IO]] пока не решен, это ayn c результат. Это будет решено в будущем как простой Future / Promise. И мы можем принудительно запустить его:

scala> val response = io.unsafeRunSync
response: org.http4s.Response[cats.effect.IO] = Response(status=200, headers=Headers())
  1. Kleisli
  2. Http4s
  3. Практическая FP в Scala от Габриэля Вольпе
2 голосов
/ 03 апреля 2020

F [_] - это просто абстракция. Это может быть List или IO чего-то другого с видом * -> *. Основная идея, что вы можете определить общие функции. Хороший пример этого - класс типов Functor и функция map внутри этого класса. Таким образом, в вашем коде вы можете сказать, что вы F - функтор (F [_]: Functor) и после него вы можете использовать функцию карты.

...