Purescript: не может соответствовать типу - PullRequest
0 голосов
/ 03 мая 2018

В REPL это работает:

> mm n = (\n -> n * 2) <$> n
> mm (2:3:Nil)
(4 : 6 : Nil)

в файле, который компилируется, и я могу запустить его:

squareOf ls =
  map (\n -> n * n)  ls

однако, когда я добавляю определение типа к этой функции

squareOf :: List Int -> Int
squareOf ls =
  map (\n -> n * n)  ls

Я получаю ошибку:

 Could not match type

    List Int

  with type

    Int


while checking that type t0 t1
  is at least as general as type Int
while checking that expression (map (\n ->
                                       (...) n
                                    )
                               )
                               ls
  has type Int
in value declaration squareOf

where t0 is an unknown type
      t1 is an unknown type

Я попытался изменить сигнатуру на псевдоним типа в списке, а также безуспешно попробовал полное определение. Если я проверю определение, созданное, когда я не помещаю подписи в свою функцию, я получу:

forall t2 t3. Functor t2 => Semiring t3 => t2 t3 -> t2 t3

Может кто-нибудь объяснить, почему моя подпись неверна, а также почему я получаю эту подпись для функции?

Приветствия

Редактировать: Спасибо за комментарии, обновив определение fn, чтобы оно также возвращало List Int, и, конечно, это решает проблему

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Вот map:

class Functor f where
  map :: forall a b. (a -> b) -> f a -> f b

Сужение до List Int и Int -> Int, компилятор выводит

map :: (Int -> Int) -> List Int -> List Int

Итак, в squareOf выражение сводится к списку целых чисел, а не целому числу. Вот почему компилятор жалуется.

0 голосов
/ 03 мая 2018

Предполагая, что ваша функция repl - это поведение, за которым вы следуете, вы пропустили оператор карты (<$>) в ваших последующих определениях.

Ваша функция repl (переменные переименованы для ясности) имеет тип:

mm :: forall f. Functor f => f Int -> f Int
mm ns = (\n -> n * 2) <$> ns

То есть: мм отображает «умноженное на два» на то, что сопоставимо » (то есть функтор)

В сторону: вы можете быть более кратким / ясным в своем определении здесь:

mm :: forall f. Functor f => f Int -> f Int
mm = map (_*2)

Это похоже на ваше squareOf определение, только теперь вы возводите в квадрат , поэтому ваше использование (*) носит более общий характер:

squareOf :: forall f. Functor f => Semiring n => f n -> f n
squareOf = map \n -> n * n

Поскольку (*) является членом класса типов Semiring.

Но подпись, которую вы дали, говорит о том, что вам нужен какой-то fold? Дайте мне знать, какой результат вы ожидаете от своей функции squareOf, и я соответствующим образом обновлю ответ.

...