Чтобы «вырезать список», чтобы в нем был только один элемент head, используйте take 1
:
> take 1 [1..]
[1]
> take 1 []
[]
> take 1 $ find2 (> 4) [1..10]
[5]
> take 1 $ find2 (> 14) [1..10]
[]
Если вам нужно реализовать собственную функцию take 1
, просто запишите ее уравнения в соответствии со всеми возможными входными данными:
take1 [] = []
take1 (x:xs) = [x]
или с filter
,
findWithFilter p xs = take1 $ filter p xs
Ваше определение find1
не соответствует выводу, который вы показываете. Скорее следующее определение будет:
find1 e (x:xs) = if e x then [x] -- you had `x`
else find1 e xs
find1 _ [] = [] -- the missing clause
Обычно предикат p
, а не e
, называют мнемоническим устройством. Крайне желательно добавлять сигнатуры типов во все ваши определения верхнего уровня.
Если у вас возникли трудности с написанием этого самостоятельно, вы можете начать без подписи, а затем спросить GHCi, какой тип он сделал, чем использовать эту подпись , если она действительно выражает ваше намерение - иначе это означает, что вы ' мы кодировали что-то другое:
> :t find1
find1 :: (t -> Bool) -> [t] -> [t]
Это похоже на первую попытку.
За исключением того, что вы действительно предполагали, что в списке вывода никогда не будет более 1 элемента: это либо []
, либо [x]
для некоторых x
, но не более одного.
Тип списка []
здесь слишком разрешительный, поэтому он не идеально подходит.
Такой тип все же существует. Он называется Maybe
: значения типа Maybe t
могут быть Nothing
или Just x
для некоторых x :: t
(читай: x
имеет тип t
):
import Data.Maybe (listToMaybe)
find22 p xs = listToMaybe $ filter p xs
Здесь нам даже не нужно было take 1
: функция listToMaybe :: [a] -> Maybe a
(читай: имеет тип функции с входом в [a]
и выводом в Maybe a
) уже берет не более одного элемента из своего ввода список, так как тип результата не допускает более одного элемента - в нем просто больше нет места. Таким образом, он правильно выражает наши намерения: создается не более одного элемента, если он есть:
> find22 (> 4) [1..10]
Just 5
> find22 (> 14) [1..10]
Nothing
Добавьте полную подпись над ее определением, когда вы уверены, что это то, что вам нужно:
find22 :: (a -> Bool) -> [a] -> Maybe a
Затем внедрите listToMaybe
самостоятельно. Чтобы сделать это, просто следуйте типам и напишите уравнения, перечисляющие случаи возможного ввода, производя соответствующее значение типа вывода в каждом случае, как мы делали с take1
выше.