#haskell
#haskell
Вопрос:
Prelude> let [x,y] = [3,4] in x*x y*y
25
Prelude> let x:[y] = [3,4] in x*x y*y
25
Prelude> let x:y = 3:4 in x*x y*y
интерактивный: 6: 5: ошибка:
* Аргумент, не являющийся переменной типа, в ограничении: Num [a]
(Используйте FlexibleContexts, чтобы разрешить это)
* При проверке выведенного типа
x :: forall a. (Num a, Num [a]) => a
В выражении: пусть x : y = 3 : 4 в x * x y * y
В уравнении для `it’: it = пусть x : y = 3 : 4 в x * x y * y
Может кто-нибудь объяснить, что происходит в первых двух операторах и почему возникает ошибка для третьего let ... in ..
оператора.
Комментарии:
1. К сожалению, ошибка неясна, но причина в следующем:
:
является ли оператор для построения списков с типомa -> [a] -> [a]
, поэтому ему нужен список в правой части:let x:y = 3:[4] in x*x y*y
. Обратите внимание, что вы не можете использовать y в качестве числовой причины2. Спасибо за помощь! Я сам нашел ответ 🙂 Это потому, что:
prepend operator
добавляет что-то в список. Здесь не было списка! Это можно решить, выполнивlet x:y:[] = 3:4:[] in x*x y*y OR let x:[y] = 3:[4] in x*x y*y
3. Пожалуйста, опубликуйте ответ на свой собственный вопрос и пометьте его как принятый (после некоторого времени ожидания). Именно так должен работать StackOverflow.
Ответ №1:
В третьем примере правая часть let
присваивания имеет вид: 3:4
. Оператор :
(cons) имеет сигнатуру типа a -> [a] -> [a]
: он принимает значение в левой части и список значений этого типа в правой части. В этом случае 3
является a
, но 4
не является списком a
( [a]
); это также a
. Это недопустимо.
Учитывая форму вашего упражнения на данный момент, есть два способа, которыми вы можете исправить это выражение: с помощью 3:[4]
или с помощью 3:4:[]
.
Если бы вы попытались запустить свой код сейчас, вы бы увидели, что он завершается с ошибкой x * x y * y
. Это потому, что ваше соответствие шаблону присваивает x
3
и y
to [4]
(одноэлементный список). Список нельзя умножить сам на себя, и его нельзя добавить к числу. Итак, еще раз, мы используем решение для правой части, с левой стороны:
let x:y:[] = 3:4:[]
in x * x y * y
Если мы добавим слишком много аннотаций типа, вы, надеюсь, сможете увидеть, где что-то идет не так:
-- These work fine
-- let [x, y] = [3, 4] in ...
example1 = let [(x :: a), (y :: a)] :: [a]
= [(3 :: a), (4 :: a)] :: [a]
in x * x y * y
-- let x:[y] = [3, 4] in ...
example2 = let ((x :: a) : ([(y :: a)] :: [a])) :: [a]
in x * x y * y
-- This is the incorrect implementation
-- let x:y = 3:4 in ...
example3 :: (Num a) => a
example3 = let (x :: a) : (y :: [a]) -- (:) :: a -> [a] -> [a]
= (3 :: a) : (4 :: a) -- 4 :: a is invalid here: require [a]
in (x :: a) * (x :: a)
(y :: [a]) * (y :: [a]) -- Trying to multiply two lists
-- This is the fixed implementation
-- let x:y:[] = 3:4:[] in ...
example3' :: (Num a) => a
example3' = let ((x :: a) : (y :: a) : ([] :: [a])) :: [a]
= ((3 :: a) : (4 :: a) : ([] :: [a])) :: [a]
in x * x y * y