Часто первый шаг к разработке проблемы с участием синонимов типа (вещи, которые выглядят как type ... = ...
), чтобы пройти через вручную заменить синоним (левую часть выражения type
) с расширением (правая рука боковая сторона). Итак:
func3 :: MySet (Eq a => a -> a)
становится:
func4 :: (Eq a => a -> a) -> Bool
Теперь GHC дает нам более полезную ошибку:
Illegal polymorphic or qualified type: Eq a => a -> a
Perhaps you intended to use RankNTypes or Rank2Types
In an expression type signature: (Eq a => a -> a) -> Bool
RankNTypes
это весело расширение, но это не очень полезно здесь. (Я объясню в одно мгновение).
As n.m. указал, что вы, вероятно, хотите сделать, это просто переместить ограничения из скобок:
func5 :: Eq a => (a -> a) -> Bool
И тогда GHC позволяет вам знать, вы также должны Num
. Кроме этого, мы имеем совершенно обычную подпись типа: ограничение до =>
, а затем обычные переменные типа и определенный тип. Это хорошо; мы обычно хотим, чтобы типы были максимально простыми (но не более).
Но давайте создадим резервную копию и рассмотрим две вещи: введите синонимы и RankNTypes
.
Во-первых, вы назвали MySet
«типом данных». Это опасный способ подумать об этом. На самом деле это синоним , что означает, что это звучит так: MySet (a -> a)
и (a -> a) -> Bool
являются буквально синонимами; они означают одно и то же. Контраст примерно data MySetD a = MySetD (a -> Bool)
. Там MySetD
на самом деле является типом данных типа «честный к Богу», который не может заменить, волей-неволей, для (a -> Bool)
и наоборот.
Второй: что случилось с RankNTypes
? Если мы обратимся, что расширение, мы могли бы написать это:
funcRN :: (forall a. (Eq a, Num a) => a -> a) -> Bool
funcRN = (\x -> (x 3) == 2)
И это то, что вы хотите с вещами как funcRN ((+) 1)
. Но как насчет этого?
g :: Int -> Int
g x = x - 1
funcRN g
Это не работает.funcRN
требует в качестве аргумента функции, которая может принимать любой тип a
такой, что a
является экземпляром Eq
и Num
. Это то, что означает бит forall a. (Eq a, Num a) =>
. С g
работает только с , Int
, это неприемлемо для подписи funcRN
.
Попробуйте это 'func3 :: (Num a, Eq a) => MySet (a -> a)' –
Это сработало! Благодаря! – marlanbar