#haskell
#хаскелл #haskell
Вопрос:
Я пытаюсь использовать map
для написания функции, которая принимает последние элементы списка списков. Например:
[ [0,0,4],[2,4,2],[1,3,5],[3,1,1] ] => [4,2,5,1]
Я написал это:
func l = map (last l)
и получил эту ошибку:
> ERROR - Type error in application
Expression : func [[0,0,4],[2,4,2],[1,3,5],[3,1,1]]
Term : [[0,0,4],[2,4,2],[1,3,5],[3,1,1]]
Type : [[c]]
Does not match : [a -> b]
Каков правильный способ сделать это?
Ответ №1:
Вы делаете неправильную вещь с last
. То, что вы пытаетесь сделать, это применить это к каждому внутреннему списку внутри внешнего списка l
. На самом деле вы применяете это к l
самому внешнему списку, и тогда map
это не имеет смысла.
Вместо этого вам нужно написать map last l
.
Вы можете увидеть правильную форму аргументов для map
из его типа:
map :: (a -> b) -> [a] -> [b]
Это означает, что map
принимает два аргумента, один типа a -> b
и другой типа [a]
.
Обратите внимание, что в вашем коде вы указываете только первый аргумент ( last l
). Это допустимая вещь, которую можно сделать в Haskell в целом (посмотрите «частичное применение» или «каррирование»), но здесь первый аргумент должен быть функцией, и last l
конечно, это не так.
В этом случае ваш список l
имеет тип [a]
, поэтому a
= [Integer]
(игнорируя числовую перегрузку). Первым аргументом должна быть функция типа [Integer] -> b
, и вы хотите использовать last
, что означает, что b
= Integer
. Таким образом, конечный результат будет иметь желаемый тип [Integer]
.
Ответ №2:
Попробуйте
func l = map last l
нет круглых скобок.
Если вы посмотрите на типы в func [[0,0,4],[2,4,2],[1,3,5],[3,1,1]
вызове, вы заметите, что, поскольку l = [[0,0,4],[2,4,2],[1,3,5],[3,1,1]]
тип l является [[c]]
, то тип last l
является [c]
, в то время как map ожидает [a -> b]
в качестве первого аргумента.
Комментарии:
1. Он попытался бы сопоставить результат с тем, к чему вы применяете
func l
, но ошибка типа при попытке передатьlast l
в качестве первого аргумента вmap
не позволяет ему когда-либо дойти до этой точки.2. да, это потому, что haskell пытается определить типы из определения функции и конкретного приложения, а они не проверяют.
Ответ №3:
Или даже при использовании обозначения без точек: f = map last
Который в ghci выдает тип:
GHCI> let f = map last
GHCI> :t f
f :: [[b]] -> [b]
GHCI> f [ [0,0,4],[2,4,2],[1,3,5],[3,1,1] ]
[4,2,5,1]