52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 83

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 83

1

Как была вычислена эта функция? Мы определили экземпляр функций для значений типа Num a => t

-> a. Если мы вспомним, что функция двух аргументов на самом деле является функцией одного аргумента:

Num a => t1 -> (t2 -> a), мы заметим, что тип Num a => (t2 -> a) принадлежит Num, теперь если мы

обозначим его за a’, то мы получим тип Num a’ => t1 -> a’, это совпадает с нашим исходным экземпляром.

Получается, что за счёт механизма частичного применения мы одним махом определили экземпляры Num

для функций любого числа аргументов, которые возвращают значение типа Num.

Итак функция f имеет вид:

\t1 t2 -> (t1 + t2) - (t1 * t2)

Подставим значения:

Функциональный калькулятор | 79

(\t1 t2 -> (t1 + t2) - (t1 * t2)) 1 2

(\t2 -> (1 + t2) - (1 * t2) 2

(1 + 2) - (1 * 2)

3 - 2

1

Теперь давайте составим несколько выражений с обобщёнными функциями. Для этого добавим в модуль

FunNat директиву импорта функций из модуля Data.Function. Также добавим несколько основных функций

для списков и класс Ord:

module FunNat where

import Prelude(Show(.. ), Eq(.. ), Ord(.. ), Num(.. ), error)

import Data.Function(id, const, (. ), ($), flip, on)

import Prelude(map, foldr, filter, zip, zipWith)

...

и загрузим модуль в интерпретатор:

Prelude> :load FunNat

[1 of 1] Compiling FunNat

( FunNat. hs, interpreted )

Ok, modules loaded: FunNat.

Составим функцию, которая принимает один аргумент, умножает его на два, вычитает 10 и берёт модуль

числа.

*FunNat> let f = abs $ id * 2 - 10

*FunNat> f 2

6

*FunNat> f 10

10

Давайте посмотрим как была составлена эта функция:

abs $ id * 2 - 10

=>

abs $ (id * 2) - 10

-- приоритет умножения

=>

abs $ (\x -> x * \x -> 2) - 10

-- развернём id и 2

=>

abs $ (\x -> x * 2) - 10

-- по определению (*) для функций

=>

abs $ (\x -> x * 2) - \x -> 10

-- развернём 10