Параметры в анонимной функции

#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 значение накопителя.