Форум программистов, компьютерный форум, киберфорум
Наши страницы
Haskell
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
Drovosek01
5 / 5 / 1
Регистрация: 20.09.2015
Сообщений: 84
1

Как понять как работает эта функция в Haskell?

19.04.2018, 19:09. Просмотров 919. Ответов 5
Метки нет (Все метки)

Я смотрю обучающее видео по haskell: https://www.youtube.com/watch?v=43zCXDb5dQ4&t=1954s

Там на 33:02 минуте говорится про функцию sumFstFst, которая в качестве аргументов принимает ещё несколько функций, среди которых функция on, +, helper.

У функции sumFstFst в объявлении нет названий аргументов, после названия сразу идёт равно и "инструкции" что надо делать.
Тем не менее при вызове SumFstSft p1 p2 каким-то образом компилятор понимает, что надо сначала helper применить к p1, потом helper применить к p2, и результаты передать в on вместе с функцией +.

Я не могу понять как это происходит, по какому принципу функция helper вызывается 2 раза и как она понимает, что нужно обработать, мы же после объявления sumFstFst никаких аргументов не указали.
Объясните, пожалуйста.
0
Миниатюры
Как понять как работает эта функция в Haskell?  
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.04.2018, 19:09
Ответы с готовыми решениями:

Форумчане, как работает эта программа (Haskell)
Множества заданы списками строк L1 и L2. Получить в виде списка L3 множество L1\L2. Код программы...

Помогите понять, как эта программа(редактор иконок) работает?
Добрый вечер, это редактор иконок, можете объяснить как эта программа работает? //iconeditor.h ...

Как работает эта функция?
Как работает эта функция?Я знаю, что она ищет простые числа, но каким образом,я не понимаю.Например...

Как работает эта функция?
Вот код программы крестики-нолики. Пожалуйста, объясните на пальцах как работает ф-ция "botMove"....

Как работает эта функция?
На просторах интернета нашёл интересную функцию, которая рисует окружность, но проблема в том, что...

5
Catstail
Модератор
25223 / 12885 / 2386
Регистрация: 12.02.2012
Сообщений: 21,017
19.04.2018, 21:04 2
Лучший ответ Сообщение было отмечено Drovosek01 как решение

Решение

Я Вам больше скажу: этот код можно было бы записать еще короче - вот так:

Haskell
1
2
sumFstFst = (+) `on` helper
   where helper = fst . fst
т.е. у вспомогательной функции helper вообще не указывать аргументов! Как ни странно, такая запись называется "бесточечная нотация", хотя пришлось использовать композицию (т.е. точку!).

В действительности ничего странного в опускании аргументов нет. Мы можем написать так:

Haskell
1
f = (+)
А потом, совершенно спокойно:

Haskell
1
2
f 2 3
5 -- что абсолютно верно
И вопроса "откуда f знает, что нужно два аргумента" не возникает. Так и с выражением sumFstFst = (+) `on` helper
В Haskell все определяют типы. Вот и посмотрим на типы всех участников выражения. Но сначала "отцепим" helper от sumFstFst:

Haskell
1
2
sumFstFst = (+) `on` helper
helper = fst . fst
Теперь посмотрим на типы участников:

Haskell
1
2
3
4
5
*Main> :t helper
helper :: ((c, b), b1) -> c
 
*Main> :t sumFstFst
sumFstFst :: ((Integer, b), b1) -> ((Integer, b), b1) -> Integer
Другими словами, компилятор понял, что аргумент helper должен быть парой, первым элементом которого тоже является пара. А sumFstFst - это "функция двух аргументов", каждый из которых является парой, первым элементом которого тоже является пара. Так что, если на вход такой функции подать ((1,2),(3,4)) ((3,4),(5,6)) то функция это "съест". Как компилятор это вычислил? Благодаря механизму вывода типов. Взял тип функции (+):

Haskell
1
2
:t (+)
(+) :: Num a => a -> a -> a  -- аргументы - два числа
и тип функции on:

Haskell
1
2
:t on
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
и скомбинировал их. Как он это сделал? Смотрим внимательно: первым аргументом on должна быть функция двух одинаковых аргументов. Подходит функция (+) по типу? Да, подходит. Вторым аргументом он должна быть функция одного аргумента, переводящая произвольный тип а в тип b. Вторым аргументом может быть почти любая одноаргументная функция, но тип ее результата должен быть таким же, как аргументы первого аргумента on! В нашем случае это числа. Функция helper подойдет по типу, при условии, что первый элемент первой пары - число. Тип остальных элементов пар роли не играет! Убедимся:

Haskell
1
2
*Main> sumFstFst ((11,'a'),("a","n")) ((22,'a'),("z","z"))
33
Теперь должно быть понятно, что запись sumFstFst = (+) `on` helper задает функцию двух аргументов вида ((Число,_),(_,_)) В функциональном выражении их можно не указывать (мы же записали f = (+), а могли бы записать более длинно: f x y = (+) x y; хаскеллеры предпочитают лаконичную запись).
2
Drovosek01
5 / 5 / 1
Регистрация: 20.09.2015
Сообщений: 84
19.04.2018, 22:23  [ТС] 3
Catstail, огромное спасибо за объяснения! 90% вопроса теперь прояснилась, но кое-что всё равно непонятно.

У нас в функцию sumFstFst передаются 2 аргумента (2 кортежа с кортежами) и, получается, к каждому кортежу применяется функция helper.
Но как так? Вызвали/передали_аргументы в sumFstFst одинажды, а helper вызывалась дважды, т.к. реализации helper написано, что берётся самый первый элемент из пары пар, а у нас 2 таких пары пар. Значит helper дважды вызывалась? (это я так понимаю...)
0
Drovosek01
5 / 5 / 1
Регистрация: 20.09.2015
Сообщений: 84
19.04.2018, 22:37  [ТС] 4
Уже всё понял по комментарию с тостера
она так работает берет бинарный оператор далее функцию и два аргумента над которыми надо произвести действие
1
Миниатюры
Как понять как работает эта функция в Haskell?  
Catstail
Модератор
25223 / 12885 / 2386
Регистрация: 12.02.2012
Сообщений: 21,017
20.04.2018, 00:01 5
Цитата Сообщение от Drovosek01 Посмотреть сообщение
Значит helper дважды вызывалась?
- да. И это делает on

Добавлено через 8 минут
Кстати, в двукратном вызове можно убедиться, используя трассировку:

Haskell
1
2
3
4
5
6
7
8
9
10
import Data.Function
import Debug.Trace
 
sumFstFst = (+) `on` helper
helper x =  trace "!!!" $ (fst . fst) x 
 
*Main> sumFstFst ((1,2),(3,4)) ((5,6),(7,8))
!!! -- первый вызов
!!! -- второй вызов
6 -- результат
2
Curry
3132 / 2148 / 262
Регистрация: 01.06.2013
Сообщений: 4,612
Записей в блоге: 9
20.04.2018, 08:18 6
Catstail всё подробно разобъяснил. Добавлю.
Цитата Сообщение от Catstail Посмотреть сообщение
запись sumFstFst = (+) `on` helper задает функцию двух аргументов вида ((Число,_),(_,_)) В функциональном выражении их можно не указывать
Это называется частичное применение.
Посмотрим на сигнатуру функции on
Haskell
1
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
В sumFstFst функции on передаются только два аргумента, по этому остаются два последних (правых) аргумента a -> a -> c, то есть получается функция из двух аргументов которая и возвращается функцией sumFstFst.

Функция же on не какая то магическая. Её можно легко сделать самим не подключая модуль Data.Function, например вот так
Прежде чем посмотреть лучше попробовать сделать самому.
on f2 f x y = f2 (f x) (f y)

Ну и лучше указывать сигнатуры функций в исходном тексте, это избавляет от многих проблем, легко находятся ошибки на этапе компиляции, сообщения компилятора становятся более понятными.
Haskell
1
2
3
4
5
6
7
8
9
10
sumFstFst :: Num a => ((a,b),(c,d)) -> ((a,b),(c,d)) -> a
sumFstFst x y = ((+) `on` helper) x y
   where helper :: ((a,b),(c,d)) -> a
         helper = fst . fst
 
p1 :: ((Int,a),(b,c))
p1 = ((1,undefined),(undefined,undefined))
 
p2 :: ((Int,a),(b,c))
p2 = ((2,undefined),(undefined,undefined))
Я использовал функцию undefined. Её можно подставить вместо чего угодно (в любое место выражения). При её вызове выдаётся сообщение об ошибке. Однако, при вычислении выражения sumFstFst p1 p2 она не вызывается за ненадобностью.
2
20.04.2018, 08:18
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.04.2018, 08:18

Не понимаю как работает эта функция
Что означают аргументы & и * в этой функции ? template <typename T> inline T* const& max(T*...

Не могли бы объяснить, как работает эта функция для удаления цифр?
char* delDig(char *S) { int i,j; i=0; for (j=0; j<strlen(S); j++) if ((S <...

Неудачная попытка понять как работает функция peek()
Чтобы понять принцип работы функции peek(), написал простенькую программку. Но даже она не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.