{ "cells": [ { "cell_type": "markdown", "id": "391efc5a", "metadata": {}, "source": [ "# Структуры данных\n", "## Ассоциативные массивы\n", "Это массивы, где индексы могут быть из произвольного (почти, хэшируемого) множества, например, числа, строки, другие неизменяемые объекты.\n", "\n", "```\n", "freq[\"cat\"] = 10\n", "freq[\"and\"] = 100\n", "```" ] }, { "cell_type": "code", "execution_count": 5, "id": "b59ba773", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Just 10" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "Nothing" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import qualified Data.Map as M\n", "\n", "-- созадние ассоциативного массива\n", "m = M.fromList [(\"cat\", 10), (\"and\", 100)]\n", "\n", "M.lookup \"cat\" m -- возвращает Maybe от значения в массиве\n", "M.lookup \"dog\" m" ] }, { "cell_type": "markdown", "id": "6a2307fd", "metadata": {}, "source": [ "Эти ассоциативные массивы неизменяемые, т.е. нельзя, например, записать в Map другое значение по ключу. Можно только создать новый Map, в котором значение изменено:" ] }, { "cell_type": "code", "execution_count": 6, "id": "339dbcc9", "metadata": {}, "outputs": [ { "data": { "text/html": [ "M.adjust :: forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a" ], "text/plain": [ "M.adjust :: forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ ":t M.adjust" ] }, { "cell_type": "code", "execution_count": 9, "id": "23a8904f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Just 10" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "Just 11" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "m2 = M.adjust (+1) \"cat\" m\n", "M.lookup \"cat\" m\n", "M.lookup \"cat\" m2" ] }, { "cell_type": "markdown", "id": "2c038e16", "metadata": {}, "source": [ "# Функторы\n", "Это класс типов, он содержит в себе те типы, которые как будто хранят внутри себя несколько других значений: список, кортеж, ассоциативный массив, MayBe, ...\n", "\n", "[https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Functor.html](https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Functor.html)" ] }, { "cell_type": "code", "execution_count": 16, "id": "b0e2a18d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[11,21,31]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "Just 11" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "Nothing" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "(10,21)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "(10,20,31)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "(\"abc\",21)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "fromList [(\"and\",101),(\"cat\",11)]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "-- List\n", "fmap (+1) [10, 20, 30] -- эквиваленто map\n", "\n", "-- MayBe\n", "fmap (+1) (Just 10)\n", "fmap (+1) Nothing\n", "\n", "-- Кортежи, функция применяется только к последнему элементу\n", "fmap (+1) (10, 20)\n", "fmap (+1) (10, 20, 30)\n", "fmap (+1) (\"abc\", 20)\n", "\n", "-- Для Map\n", "fmap (+1) m -- это ассоциативный массив про кота" ] }, { "cell_type": "markdown", "id": "8e3a9c27", "metadata": {}, "source": [ "Можно увидеть, что функторами являются функции: `Functor ((->) r)` — это функции из типа r в какой-то другой. Функция хранит множество значений, для каждого аргумента своё значение. fmap для функции говорит, какую функцию применить к результату вычисления этой функции." ] }, { "cell_type": "code", "execution_count": 23, "id": "64c2df39", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Avoid lambda using `infix`
Found:
(\\ x -> x ++ \"!\")
Why Not:
(++ \"!\")
" ], "text/plain": [ "Line 6: Avoid lambda using `infix`\n", "Found:\n", "(\\ x -> x ++ \"!\")\n", "Why not:\n", "(++ \"!\")" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\"4242\"" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\"\\\"abc\\\"\\\"abc\\\"\"" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\"4242!\"" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "f :: Show a => a -> String\n", "f x = show x ++ show x\n", "f 42\n", "f \"abc\"\n", "\n", "f2 = fmap (\\x -> x ++ \"!\") f\n", "f2 42" ] }, { "cell_type": "markdown", "id": "efa4efcf", "metadata": {}, "source": [ "Можно сделать функтором наши собственные структуры. Например, дерево. fmap будет заменять по указанному правилу каждое значение в дереве.\n", "\n", "При реализации функтора важно, чтобы\n", "1. fmap id X = X (т.е. пусая функция id = \\x -> x ничего не должна менять). В документации сделано так fmap id X = id X, сокращаем X, получается fmap id = id\n", "2. сделать fmap дважды с функциями f и g должно быть эквивалентно тому, что fmap делается один раз с композицией:\n", " `(fmap g (fmap f X)) = fmap (g.f) X`" ] }, { "cell_type": "code", "execution_count": 25, "id": "69ab8269", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Functor law
Found:
fmap (* 2) (fmap (+ 1) [10, 20, 30])
Why Not:
fmap ((* 2) . (+ 1)) [10, 20, 30]
" ], "text/plain": [ "Line 1: Functor law\n", "Found:\n", "fmap (* 2) (fmap (+ 1) [10, 20, 30])\n", "Why not:\n", "fmap ((* 2) . (+ 1)) [10, 20, 30]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "[22,42,62]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "[22,42,62]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fmap (*2) (fmap (+1) [10, 20, 30])\n", "fmap ((*2) . (+1)) [10, 20, 30]" ] } ], "metadata": { "kernelspec": { "display_name": "Haskell", "language": "haskell", "name": "haskell" }, "language_info": { "codemirror_mode": "ihaskell", "file_extension": ".hs", "mimetype": "text/x-haskell", "name": "haskell", "pygments_lexer": "Haskell", "version": "8.10.4" } }, "nbformat": 4, "nbformat_minor": 5 }