#haskell #lambda #anonymous-function
#haskell #лямбда #анонимная функция
Вопрос:
Я практиковался с анонимными функциями и получил следующее:
takeWhile' :: (a -> Bool) -> [a] -> [a]
takeWhile' f xs = foldl (x y z -> if (f x) amp;amp; z then x : y else y) xs [] True
по сути, это перезапись функции takeWhile, которая уже есть в Haskell.
Для тех, кто не знает, функция takeWhile принимает список и функцию и возвращает новый список с каждым элементом в исходном списке, который удовлетворяет функции, пока один из них не даст false .
С моей точки зрения, все кажется правильным, у меня есть 3 аргумента x, y и z, готовых к использованию в моей анонимной функции, x — список чисел, y — пустой список, в который я буду вставлять каждый элемент, а z — это, по сути, средство удаления, так что, если один из элементов несоответствуют требованиям, мы больше не вставляем.
И все же Haskell выдает мне следующую ошибку:
"Occurs check: cannot construct the infinite type: a ~ Bool -> [a]"
Есть идеи, почему?
Комментарии:
1. Если вы не планируете
xs
представлять собой список функций и предоставлять функцию в качестве начального значения, анонимная функция может принимать только два аргумента.2. Я думаю, что это должно быть a
foldr
, поскольку это единственный способ, которым применение сгиба может быть сведено к применению лямбда-выражения, позволяющего предоставить третий параметр.3.
foldl
принимает два параметра: накопительx
и элементy
. Что здесьz
делает?
Ответ №1:
Функция fold в fold
принимает в качестве параметров накопитель x
и элемент y
. Таким образом, нет z
того, что передается.
Но даже если бы это было как-то возможно, все еще есть другие проблемы. x
является ли здесь накопителем, то есть списком, это означает, что x : y
это не имеет смысла, поскольку (:) :: a -> [a] -> [a]
принимает элемент и список и создает новый список.
Однако вы можете легко использовать foldr
для реализации takeWhile
функции. Действительно:
takeWhile' p = foldr (x -> if p x then (x :) else const []) []
Таким образом, мы здесь проверяем, выполняется ли предикат, если это так, мы предварительно загружаем накопитель x
. Если нет, мы возвращаем []
, независимо от значения аккумулятора.
Из-за лени foldr
, он не будет искать элементы после того, как элемент вышел из строя накопителя, так const []
как будет ingore значение накопителя.