Главное меню
Мы солидарны с Украиной. Узнайте здесь, как можно поддержать Украину.

Haskell: II

Автор arseniiv, марта 4, 2012, 22:04

0 Пользователи и 1 гость просматривают эту тему.

arseniiv

Итак, сейчас возьмёмся за ум.

δ: Функции с внешней стороны
> not True
False
> 2 > 3 || 2 < 3
True
> 'a' <= 'b' && not (not False)
False


Из этого можно сделать несколько выводов:
‣ приоритет II, && ниже приоритетов операций сравнения, и это удобно. В C вот тоже, а в Delphi не так, и приходится использовать скобки;
‣ скобки вокруг аргументов (по крайней мере, для унарных функций) ставить не надо. В действительности, пробел понимается как операция применения функции и имеет высший приоритет — потому они не нужны;
‣ символы можно сравнивать, и пр..

Операции — тоже функции, просто имеющие инфиксный синтаксис. Любую бинарную функцию можно записать таким образом, окружив её обратными апострофами. Наоборот, имя операции можно окружить скобками и поставить аргументы справа:

> (++) "Mamma " "mia"
"Mamma mia"
> [5 `mod` 3, 5 `rem` 3]
[2,1]


Можно окружить скобками и операцию, слева или справа от которой находится аргумент — конструкция, называемая сечением. Результатом будет функция, ждущая оставшийся аргумент.

> (2 +) 3
5
> (`div` 4) 8
2


Так же можно поступать и с функциями, не инфиксно записанными:

> (div 8) 7
1


И это, и сечения — виды частичного применения, которое позволяет конструировать из функции функцию с меньшим количеством аргументов. На самом деле, f a b и вычисляется как (f a) b.

ε: Ещё некоторые стандартные функции
> 'd' == 'e'
False
> "E" /= "F"
True
> [max 0 7, min 0 7]
[7,0]


Плюс сравните:

> [quot (-8) 3, rem (-8) 3]
[-2,-2]
> [div (-8) 3, mod (-8) 3]
[-3,1]


О функциях над списками и кортежами я расскажу чуть позже.

ζ: Функции с внутренней стороны
Допишу на следующий день, надо идти спать.

Python

rem - остаток от деления? quot чем-то отличается от rem?
Пролетареві ніколи вчити європейських мов, бодай би свою знати добре і на ній принести до своєї хати світло знання (Гнат Хоткевич)
ÆC CASALI NAXI PRASQURI: AHOV CÆRU, MERTVÆRI TÆ SLAVUTÆT!
Вони просили його: «Скажи: кетум», а він говорив: «сатем», і не міг вимовити правильно.
Хотелось бы также отметить, что "Питон" - это "мышиный язык" : "пи+тон". © АБР-2

Тайльнемер

Цитата: Python от марта  6, 2012, 19:40
rem - остаток от деления? quot чем-то отличается от rem?
Насколько я понял, quot и rem — это то же, что и / и % (соответственно) в Си.

Кстати, кто-нибудь сталкивался с тем, чтобы эти операции (а не Div и Mod) понадобились на практике?

arseniiv

(Руки никак не дойдут дописать, как нехорошо. :( Мог бы уже десятый писать, тем более что они маленькие.)

Вообще, те мои примеры на них не очень показательны (тфу, да нет, они совершенно не показательны. Я перепишу потом). Вот показательный:

> map (`div` 3) [-6..6]
[-2,-2,-2,-1,-1,-1,0,0,0,1,1,1,2]
> map (`quot` 3) [-6..6]
[-2,-1,-1,-1,0,0,0,0,0,1,1,1,2]
> map (`mod` 3) [-6..6]
[0,1,2,0,1,2,0,1,2,0,1,2,0]
> map (`rem` 3) [-6..6]
[0,-2,-1,0,-2,-1,0,1,2,0,1,2,0]


(Хорошо, что пока всё это читают только люди, знающие, откуда и куда map. Быть последовательным достаточно сложно... Опять же, постараюсь писать более понятно сразу.)

arseniiv

Так, пока к слову. Надо было написать раньше:

Условное выражение.

Выражение if e then a else b вычисляется в a, если e оказалось True и в b в противном случае. Можно легко заметить, что a и b должны иметь один тип.

Вполне можно обходиться без него, но для этого мне надо дописать о конструировании функций. Ну и, как обычно бывает, в одном случае лучше выглядит это, а в другом то.

basta

и всё? а где лямбда функции замыкаются и редуцируются, монады одна в другую трансформируются, санки форсятся и происходит разная другая магия (с) ?

basta

Prelude> (\x->concat $ words x) "ktulhu fxtagn desu "
"ktulhufxtagndesu"


или

Prelude> (\x->filter (/=' ') x) " ave maria"
"avemaria"

arseniiv

Offtop
Прокрастинация, чтоб её... У меня в голове пока что ещё видится славное здание, но уже смутно.

basta

Лямбда - это как анонимная функция в с++, и совсем то же самое, что и в лиспах. Наклонная палочка \ очень похожа на греческую букву, у которой отняли ножку, но в хаскеле она всё равно твёрдо стоит на математическом основании. Я много раз пытался понять статью в википедии про лямбда-исчисление, но мне всякий раз не хватало каких-то знаний. Но на самом деле понимать всё-всё не нужно. Схема такая:

{- так оформляются комментарии! -}
-- и ещё вот так (во всю строку)

\ {- локальная переменная -} x -> {- собственно функция -} f x

-- с большим количеством переменных поступают так

\x-> \y-> \z-> f x y z

-- но в хаскеле также используется упрощенная запись

\m n p-> m + n ^ p


Хотя часто лямбду может заменить частичное применение, которое есть следствие каррирования. Как в моём примере про удаление пробелов: (/=' ') -- существует стандартная функция /= "не равно" с двумя аргументами, один из них уже подставлен, а второй нет, и когда всё это заключено в скобки -- получается функция ожидающая второй аргумент, в данном случае, видимо с типом Char. А можно ли указать типы у лямбды и как это делается?

arseniiv

Цитата: basta от апреля 29, 2012, 06:37
А можно ли указать типы у лямбды и как это делается?
Как и с любым выражением, выражение :: тип:

> :t ((\x -> x * 2) :: Int -> Int)
((\x -> x * 2) :: Int -> Int) :: Int -> Int
> :t (\x -> x * 2)
(\x -> x * 2) :: Num a => a -> a