Учебник по Haskell - [28]

Шрифт
Интервал

,

если они не содержат знаков после точки, и к Double – если содержат.

*Nat Prelude> let f = (1.5 + )

*Nat Prelude> :t f

f :: Double -> Double

*Nat Prelude> let x = 5 + 0

*Nat Prelude> :t x

x :: Integer

*Nat Prelude> let x = 5 + Zero

*Nat Prelude> :t x

x :: Nat

Умолчания определены только для класса Num. Для этого есть специальное ключевое слово default. В

рамках модуля мы можем указать какие типы считаются числами по умолчанию. Например, так (такое умол-

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

default (Integer, Double)

Работает правило: если произошла неопределённость и один из участвующих классов является Num, а все

остальные классы – это стандартные классы, определённые в Prelude, то компилятор начинает последова-

тельно пробовать все типы, перечисленые за ключевым словом default, пока один из них не подойдёт. Если

такого типа не окажется, компилятор скажет об ошибке.

Ограничение мономорфизма

С выводом типов в классах связана одна тонкость. Мы говорили, что не обязательно выписывать типы

выражений, компилятор может вывести их самостоятельно. Например, мы постоянно пользуемся этим в ин-

терпретаторе. Также когда мы говорили о частичном применении, мы сказали об очень полезном умолчании

в типах функций. О том, что за счёт частичного применения, все функции являются функциями одного аргу-

мента. Эта особенность позволяет записывать выражения очень кратко. Но иногда они получаются чересчур

краткими, и вводят компилятор в заблуждение. Зайдём в интерпретатор:

Prelude> let add = (+)

Prelude> :t add

add :: Integer -> Integer -> Integer

Мы хотели определить синоним для метода плюс из класса Num, но вместо ожидаемого общего типа

получили более частный. Сработало умолчание для численного типа. Но зачем оно сработало? Если мы

попробуем дать синоним методу из класса Eq, ситуация станет ещё более странной:

Prelude> let eq = (==)

Prelude> :t eq

eq :: () -> () -> Bool

Мы получили какую-то ерунду. Если мы попытаемся загрузить модуль с этими определениями:

52 | Глава 3: Типы

module MR where

add = (+)

eq

= (==)

то получим:

*MR> :l MR

[1 of 1] Compiling MR

( MR. hs, interpreted )

MR. hs:4:7:

Ambiguous type variable ‘a0’ in the constraint:

(Eq a0) arising from a use of ==

Possible cause: the monomorphism restriction applied to the following:

eq :: a0 -> a0 -> Bool (bound at MR.hs:4:1)

Probable fix: give these definition(s) an explicit type signature

or use -XNoMonomorphismRestriction

In the expression: (==)

In an equation for ‘eq’: eq = (==)

Failed, modules loaded: none.

Компилятор жалуется о том, что в определении для eq ему встретилась неопределённость и он не смог

вывести тип. Если же мы допишем недостающие типы:

module MR where

add :: Num a => a -> a -> a

add = (+)

eq :: Eq a => a -> a -> Bool

eq

= (==)

то всё пройдёт гладко:

Prelude> :l MR

[1 of 1] Compiling MR

( MR. hs, interpreted )

Ok, modules loaded: MR.

*MR> eq 2 3

False

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

вывести тип, и тип окажется общим. Это можно проверить в интерпретаторе. Для этого начнём новую сессию:

Prelude> let eq a b = (==) a b

Prelude> :t eq

eq :: Eq a => a -> a -> Bool

Prelude> let add a = (+) a

Prelude> :t add

add :: Num a => a -> a -> a

Запишите эти выражения в модуле без типов и попробуйте загрузить. Почему так происходит? По смыслу

определения

add a b = (+) a b

add

= (+)

ничем не отличаются друг от друга, но второе сбивает компилятор столку. Компилятор путается из-

за того, что второй вариант похож на определение константы. Мы с вами знаем, что выражение справа от

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

возможно константа, потому что она выглядит как константа. У таких возможно-констант есть специальное

имя, они называются константными аппликативными формами (constant applicative form или сокращённо

CAF). Константы можно вычислять один раз, на то они и константы. Но если тип константы перегружен,

и мы не знаем что это за тип (если пользователь не подсказал нам об этом в объявлении типа), то нам

приходится вычислять его каждый раз заново. Посмотрим на пример:

Проверка типов | 53

res = s + s

s = someLongLongComputation 10

someLongLongComputation :: Num a => a -> a

Здесь значение s содержит результат вычисления какой-то большой-пребольшой функции. Перед компи-

лятором стоит задача вывода типов. По тексту можно определить, что у s и res некоторый числовой тип.

Проблема в том, что поскольку компилятор не знает какой тип у s конкретно в выражении s + s, он вы-

нужден вычислить s дважды. Это привело разработчиков Haskell к мысли о том, что все выражения, которые

выглядят как константы должны вычисляться как константы, то есть лишь один раз. Это ограничение называ-

ют ограничением мономорфизма. По умолчанию все константы должны иметь конкретный тип, если только

пользователь не укажет обратное в типе или не подскажет компилятору косвенно, подставив неопределённое

значение в другое значение, тип которого определён. Например, такой модуль загрузится без ошибок:

eqToOne = eq one

eq = (==)

one :: Int

one = 1

Только в этом случае мы не получим общего типа для eq: компилятор постарается вывести значение,


Рекомендуем почитать
Уголовное право. Особенная часть

В книге кратко изложены ответы на основные вопросы темы «Уголовное право. Особенная часть». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.


Уголовно-исполнительное право

В книге кратко изложены ответы на основные вопросы темы «Уголовно-исполнительное право». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.


Самоучитель Adobe Premiere 6.5

Книга посвящена возможностям самого популярного средства цифрового видеомонтажа – Adobe Premiere 6.5. Описываются основные приемы работы с программой, приводятся сведения об управлении проектами и клипами, обсуждаются методы монтажа видео и звука, техника создания титров и добавления спецэффектов, а также освещается процесс окончательного монтирования фильма. На примерах рассматриваются все этапы создания и обработки фильмов для телевидения, видео и мультимедиа.Для широкого круга пользователей.


Финансовое право

В учебном пособии в краткой и доступной форме рассмотрены все основные вопросы, предусмотренные государственным образовательным стандартом и учебной программой по дисциплине «Финансовое право».Книга позволит быстро получить основные знания по предмету, а также качественно подготовиться к зачету и экзамену.Рекомендуется студентам, аспирантам и преподавателям по юридическим, экономическим и управленческим специальностям, а также сотрудникам банков.Автор книги, Шевчук Денис Александрович, имеет опыт преподавания различных дисциплин в ведущих ВУЗах Москвы (экономические, юридические, технические, гуманитарные), два высших образования (экономическое и юридическое), более 30 публикаций (статьи и книги), Член Союза Юристов Москвы, Член Союза Журналистов России, Член Союза Журналистов Москвы, Стипендиат Правительства РФ, опыт работы в банках, коммерческих и государственных структурах (в т.ч.


фгос  ответы

Содержащиеся в пособии контрольно-измерительные материалы (КИМы) для 5 класса, аналогичные материалам ЕГЭ, составлены в соответствии с программой общеобразовательных учреждений по русскому языку и учитывают возрастные особенности учащихся. В конце пособия даны ответы на все варианты тестов, предложены диктанты различных типов.Пособие адресовано учителям, ученикам, их родителям и всем, кому необходимо закрепить и систематизировать знания перед ЕГЭ.


Теория литературы. Чтение как творчество

Цель предлагаемого пособия – систематизировать и обогатить представления о природе, структуре и особенностях художественной литературы как вида искусства, помочь совершенствованию читательского мастерства. Книга снабжена кратким словарем основных литературоведческих понятий и терминов (составлен при участии доцента О.В. Быстровой).Для студентов филологических факультетов, учителей, преподавателей литературы высших и средних учебных заведений.