2015-11-14 4 views
0

В Haskell, я просто знаю, чтоЧто такое '(плавающий a, Num (a -> a))' в Haskell?

:type ((+)(1)) 
((+)(1)) :: Num a => a -> a 
((+)(1) 2 
3 

Но как насчет

:type abs(sqrt) 
abs(sqrt) :: (Floating a, Num (a -> a)) => a -> a 

На самом деле, я стараюсь много раз, но не использовать функцию 'абс (SQRT)'. Тогда у меня есть несколько вопросов. Каков тип (класс?) '(Floating a, Num (a -> a))? Можно ли использовать функцию «abs (sqrt)»? Как?

+2

Я голосую, чтобы закрыть этот вопрос как не по теме, потому что кажется, что вы никогда не потрудились проверить базовое введение в Haskell. Я честно удивляюсь, что заставило вас думать, что 'abs (sqrt)' будет работать и что заставило вас использовать такой синтаксис. –

+1

@OtosakaYuu: это 'abs sqrt' не' abs (sqrt) '- последнее вводит в заблуждение как вы, так и некоторые другие люди; то есть о '((+1) (1))', который на самом деле jus t' ((+) 1) '(no parens вокруг' 1'), а секции операторов упрощают это до '(1 +)' even , Знание и соблюдение таких правил приведет к лучшему пониманию Haskell и чистого, идиоматического, профессионально выглядящего кода. –

ответ

0

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

class Show a where 
    show :: a -> String 

Это говорит о том, что любой тип, который реализует Show класса типов могут быть преобразованы в String (есть еще некоторые осложнения для более реалистичных ограничений, но точка Show должна иметь возможность преобразовывать значения в String с).

В этом случае функция show имеет полный тип Show a => a -> String.

Если мы рассмотрим функцию sqrt, его тип

> :type sqrt 
sqrt :: Floating a => a -> a 

И abs:

> :type abs 
abs :: Num b => b -> b 

Если вы спросите GHCI какие типы он будет использовать тип переменной a в обоих случаях , но я использовал b в сигнатуре типа для abs, чтобы было ясно, что это разные переменные типа с тем же именем, и это поможет избежать путаницы на следующем шаге.

Эти сигнатуры типа означают, что sqrt принимает значение, тип которого реализует Floating класса типов (используйте :info Floating для просмотра всех пользователей) и возвращает значение того же типа, и что функция abs принимает значение, тип которого реализует Num typeclass и возвращает значение того же типа.

Выражение abs(show) эквивалентным образом анализируется как abs sqrt, а это означает, что sqrt это первый и единственный аргумент, передаваемый abs. Однако мы просто сказали, что abs принимает значение Num, но sqrt - это функция, а не число. Почему Хаскелл принимает это вместо того, чтобы жаловаться? Причину можно увидеть более четко, когда мы выполняем подстановку сигнатур типов. Так как sqrt имеет тип Floating a => a -> a, это должно совпадать с аргументом b в подписи abs, поэтому, заменив b на Floating a => a -> a, мы получим, что abs sqrt :: (Floating a, Num (a -> a)) => a -> a.

Haskell фактически позволяет использовать тип функции для реализации класса Num, вы можете сделать это самостоятельно, хотя это, вероятно, будет бессмысленным. Однако, просто потому, что что-то не имеет смысла для GHC, пока типы могут быть решены чисто, это позволит.

Вы не можете использовать эту функцию, она просто не имеет смысла. Нет встроенного экземпляра Num (a -> a) для любого a, поэтому вам нужно будет определить свой собственный. Вы можете, однако, составляют функции abs и sqrt используя оператор композиции .:

> :type abs . sqrt 
abs . sqrt :: Floating c => c -> c 

И это имеет смысл. Эта функция эквивалентна

myfunc x = abs (sqrt x) 

Здесь следует отметить, что x сначала наносят sqrt, а затем результат этого вычисления передается abs, а не передавая функцию sqrt в abs.

+0

Большое спасибо, я полностью понимаю это сейчас. Хаскелл такой интересный :) – OtosakaYuu

0

Возможно, использовать эту функцию невозможно.

Что, вероятно, происходит здесь в том, что тип говорит, что abs(sqrt) имеет ограничения, которые должны быть a типа класса Floating и (a -> a) должны быть типа класса Num. Другими словами, функция sqrt должна быть обработана так, как если бы это был номер.

К сожалению, sqrt не относится к типу класса Num, поэтому не будет никаких данных, которые будут работать здесь (не так, чтобы это имело смысл в любом случае). Однако некоторые версии GHCi позволяют вам получить тип, как если бы это было возможно.

Посмотрите на Haskell type length + 1 для аналогичного типа проблемы.

Как сказал ErikR, возможно, вы намеревались написать abs . sqrt.

+1

Эй, этот ответ выглядит знакомым ... – bheklilr

+0

Хе-хе, хороший шаблонный ответ – tangrs

+0

Эта аналогичная проблема мне очень помогает, THX! – OtosakaYuu

1

Когда вы видите Num (a -> a), это означает, что вы где-то допустили ошибку.

Возможно, вы действительно хотели: abs . sqrt, который имеет тип Floating c => c -> c - то есть это функция плавающего типа (например, Float, Double) для того же плавающего типа.

+0

Я понял. Большое спасибо. – OtosakaYuu

Смежные вопросы