260 likes | 473 Views
Refrential transparency. Что такое ‘ побочный эффект ’ ? Прозрачность по ссылкам ( referential transparency) … f 5 + … f 5 … Вызовы с одинаковыми параметрами всегда дают одинаковые значения Можно заменить на один вызов x = f 5 … x + … x …. Не очень понятно: А как же случайные числа??
E N D
Refrential transparency • Что такое ‘побочный эффект’? • Прозрачность по ссылкам (referential transparency) … f 5 + … f 5 … • Вызовы с одинаковыми параметрами всегда дают одинаковые значения • Можно заменить на один вызовx = f 5… x + … x … Не очень понятно: • А как же случайные числа?? • А как же ввод/вывод??
((2^2)^2)…^2 f n = (((2^2)^2)…^2)^2 f (n-1) f 0 = 2 f n = f (n-1)^ 2 Еще одно решение: f 0 = 2 f n = f (n-1)* f (n-1) f 10 f 9 – 2 раза f 8 – 4 раза f 7 – 8 раз … f 0 – 1024 раза O(2^n) :(
0+1/(1+1/(2+1/3+…)) b n = 0+1/(1+1/(2+1/3+…)) • При трудностях помогает доп.параметр • b’ k n = k+1/(k+1+1/(...+1/n))) b n = b' 0 n b' k n = if (k == n) then n else k + 1 / b' (k+1) n
sumsqr (1+2+...+n)^2 - (1^2 + 2^2 +... + n^2) Накапливающие параметры s s2 0 0 1 1^2 1+2 1^2 + 2^2 1+2+3 1^2 + 2^2 + 3^2 … sumsqr n = sumsqr' n 0 0 sumsqr' 0 s s2 = s^2 - s2 sumsqr' n s s2 = sumsqr' (n-1) (s+n) (s2+n^2) s s+n s2 s2+n^2 5
sumfact 1!+2!+3!+…+n! Желательно O(n) i p s 1 1 0 2 11 3 1*2 1+1*2 4 1*2*3 1+1*2+1*2*3 5 1*2*3*4 1+1*2+1*2*3+1*2*3*4 sumfact n = sumfact' n 1 1 0 sumfact' 0 i p s = s sumfact' n i p s = sumfact' (n-1) (i+1) (p*i) (s+p*i) i i+1 p p*i s s+p*i 6
Безымянная переменная (wildcard) sumfact' 0 i ps = s Лучше так: sumfact' 0 _ _ s = s _ - безымянная переменная (wildcard) Только слева от = с с 7
let sumfact' n i p s = sumfact' (n-1) (i+1) (p*i) (s+p*i) Еще одна проблема(небольшаяв данном случае) p*i – два раза DRY (Don’t Repeat Yourself) sumfact' n i p s = let p’ = p*i in sumfact' (n-1) (i+1) p’ (s+p’) с с 8
let в общем случаеДвумерныйсинтаксис let правило1 правило2 … in выражение • Могут быть и правила с параметрами • М.б. частью выражения f n = 1 + let i = 55 j = n*n + 5* n + 8 g k = k * j in g n * 2 Где кончается правило и начинается следующее? • Двумерный синтаксис (off-side rule) • Запоминаем позицию первой лексемы после let (iвпримере) • Правее продолжение правила • На том же уровне новое правило • Левее конец конструкции 9
Явное задание синтаксиса let правило1 правило2 … in выражение • Можно использовать { ; }, тогда отступы не имеют значение let{правило1; правило2; правило3} in выражение 10
where sumfact' n i p s = sumfact' (n-1) (i+1) p’ (s+p’) where p’ = p*i левая часть = правая частьwhere вспомогательные определения • Разница: • let можно писать где угодно • where – часть правила • Тоже двумерный синтаксис
Списки • Основной тип данных • (и почти во всех функциональных языках) • Примеры: [1, 2, 3] [3.5, 2.123, 98.14] [True, False] • Элементы д.б. одного типа! [1, True, 2] -- Ошибка! Потому что Хаскел статически типизированный язык (и тут мы обсуждали, что это значит).
Как создавать списки Оператор : • Оператор : • Приписать элемент в начало 1 : [2,3] [1,2,3] • Пример: f 0 = [] f n = n : f (n-1) • Список чисел от n до 1 • Кстати:[a..b] – числа от a до b с шагом 1 • На самом деле, [1,2,3] – это просто сокращение! • [1, 2, 3] – сокращение для 1:2:3:[] • Так и хранится: : / \ 1 : / \ 2 : / \ 3 []
Как обрабатывать списки – способ 1 • head – первый элемент списка • tail – все,кроме первого элемента («хвост») head [1,2,3] 1 tail [1,2,3] [2,3] • Пример: сумма элементов списка sum [] = 0 sum xs = head xs + sum(tail xs) Замечания: • Типичные имена для списков в Haskel: xs, ysи т.д. • sum – на самом деле, есть такая стандартная функция
ШаблоныКак обрабатывать списки – способ 2 sum [] = 0 sum (x:xs) = x + sum xs • Слева от = м.б. выражение с переменными – шаблон (pattern) • Шаблоны м.б. довольно сложным • Примеры: f [x] f [x, y, z] f [1, y, 2] f (x:y:xs) f (x:1:xs) Замечания: • sum (x:xs) – скобки нужны! • Еще раз, правило линейности: • f [x, y, x] -- ошибка!
Еще пример • product – произведение чисел списка (стандартная функция) product [] = 1 product (x:xs) = x * product xs • Снова факториал fact n = product [1..n] • Это стиль Haskell! • Fritz RuehThe Evolution of a Haskell Programmerhttp://www.willamette.edu/~fruehr/haskell/evolution.html
++ • Еще одна стандартная функция • Конкатенация [1,2] ++ [3,4] [1,2,3,4] [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys) • Кстати: как приписывать в конец списка • xs : x • Нет!: приписывает только в начало! • xs ++x • Нет!++ работает только со списками! • xs ++ [x] • OK • Но O(n) – медленно!
Пример: map Начальник приказывает: • Взять синус от всех элементов списка sinAll [] = [] sinAll (x:xs) = sin x : sinAllxs • Взять косинус от всех элементов списка cosAll [] = [] cosAll (x:xs) = cos x : cosAllxs • Возвести все элементы списка в квадрат • DRY :( Надо что-то делать! • map map f [] = [] map f (x:xs) = f x : map f xs • Примеры вызова map sin [1,2,3] [sin 1, sin 2, sin 3] map sqr [1,2,3] [1,4,9] • Функция высшего порядка!
Лямбда-выражения • Почему в обычных языках (Паскаль, C) этим мало пользуются? • Еще задача: Каждое число в списке умножить на 10 и прибавить 5. f x = 10 * x + 5 map f xs • Надо описывать вспомогательные функции – лень • Надо придумывать имена – тоже лень • Лямбда-выражение – функция без имени • \i -> 10*i + 5 map (\i -> 10*i+5) xs • Синтаксис: \ параметр1 параметр2 ->выражение • \ - то, что осталось от λ • Ограничения: • М.б. только одно правило (но case) • Естественно, не м.б. рекурсивно
trace, show import Debug.Trace … trace строка значение … • Возвращает значение • Печатает строку • Пример: fact 0 = trace "!!!" 1 • show • show 66 "66" • Не требует import, есть почти для всех обьектов • show [1,2,3] "[1,2,3]" • Примеры trace + show:abs x = if x > 0 then x else trace (show x) (-x)fact i = trace (show i) i *fact (i-1)
Функции высшего порядка в C#Как описыватьпараметры-функции • Как описывать параметры – функции • Как задавать значения для параметров-функций • Как описывать: Func<int, int> f • Func<тип1, тип2, … ,тип_результата> Func<int, double, bool> • Это сокращение для delegate • Специальные случаи: • Predicate<int> pred • функция с одним параметром и логическим значением • Action<int> act Action<int, double> act1 • Функция возвращает void
Как задавать значения для параметров-функций • Что можно передавать в функцию с параметром-функцией? • Имя статического метода • Expression lambdaпараметр => выражение или (параметр, параметр, …) => выражение i => i*i (i, j) => i + j • Можно указывать типы (но обычно не нужно) (int i, int j) => i + j • Statement lambdaпараметр => блок или (параметр1, параметр, …) =>блок n => { int p = 0; for(int i=1;i<=n;i++) p*=i; return p; } • Есть еще возможности (delegate, не статические методы…)
Пример static void PrintTable( Func<int, int> f, int n) { for (int i = 0; i <= n; i++) { Console.WriteLine("{0} {1}", i, f(i)); } } static int Cube(int i) { return i * i * i; } // Примеры вызова: PrintTable(Cube, 10); Func<int, int> sqr = i => i * i; PrintTable(sqr, 10); PrintTable(i => i*i, 10);