Reputation: 674
I try to implement own safe search element by index in list. I think, that my function have to have this signature:
safe_search :: [a] -> Int -> Maybe a
safe_search xs n = foldr iteration init_val xs n
iteration = undefined
init_val = undefined
I have problem with implementation of iteration. I think, that it has to look like this:
safe_search :: [a] -> Int -> Maybe a
safe_search xs n = foldr iteration init_val xs n
where
iteration :: a -> (Int -> [a]) -> Int -> a
iteration x g 0 = []
iteration x g n = x (n - 1)
init_val :: Int -> a
init_val = const 0
But It has to many errors. My intuition about haskell is wrong.
Upvotes: 1
Views: 1529
Reputation: 71109
you have
safe_search :: [a] -> Int -> Maybe a
safe_search xs n = foldr iteration init_val xs n
if null xs
holds, foldr iteration init_val []
=> init_val
, so
init_val n
must make sense. Nothing to return, so
= Nothing
is all we can do here, to fit the return type.
So init_val
is a function, :: Int -> Maybe a
. By the definition of foldr
, this is also what the "recursive" argument to the combining function is, "coming from the right":
iteration x r
but then this call must also return just such a function itself (again, by the definition of foldr
, foldr f z [a,b,c,...,n] == f a (f b (f c (...(f n z)...)))
, f :: a -> b -> b
i.e. it must return a value of the same type as it gets in its 2nd argument ), so
n | n==0 = Just x
That was easy, 0-th element is the one at hand, x
; what if n > 0
?
| n>0 = ... (n-1)
Right? Just one more step left for you to do on your own... :) It's not x
(the list's element) that goes on the dots there; it must be a function. We've already received such a function, as an argument...
To see what's going on here, it might help to check the case when the input is a one-element list, first,
safe_search [x] n = foldr iteration init_val [x] n
= iteration x init_val n
and with two elements,
[x1, x2] n = iteration x1 (iteration x2 init_val) n
-- iteration x r n
Hope it is clear now.
edit: So, this resembles the usual foldr
-based implementation of zip
fused with the descending enumeration from n
down, indeed encoding the more higher-level definition of
foo xs n = ($ zip xs [n,n-1..]) $
dropWhile ((>0) . snd) >>>
map fst >>>
take 1 >>> listToMaybe
= drop n >>> take 1 >>> listToMaybe $ xs
Upvotes: 5
Reputation: 176
I suggest to use standard foldr
pattern, because it is easier to read and understand the code, when you use standard functions:
foldr
has the type foldr :: (a -> b -> b) -> [a] -> b -> [b]
,
where third argument b
is the accumulator acc
for elements of your list [a]
.[a]
to acc
after you've added desired element of your list. Then you take head
of the resulting list [b]
and thus get desired element of the list [a]
. n
'th element of the list xs
, you need to add length xs - n
elements of xs
to the accumulator acc
, counting from the end of the list. foldr
function to improve the readability of our code? We can use it in our accumulator, representing it as a tuple (acc, iterator)
. We subtract 1
from the iterator
each turn we add element from our initial list xs
to the acc
and stop to add elements of xs
to the acc
when our iterator
is equal 0
. head . fst
to the result of our foldr
function to get the desired element of the initial list xs
and wrap it with Just
constructor. length - 1
of our initial list xs
is less than the index of desired element n
, the result of the whole function safeSearch
will be Nothing
. Here is the code of the function safeSearch
:
safeSearch :: Int -> [a] -> Maybe a
safeSearch n xs
| (length xs - 1) < n = Nothing
| otherwise = return $ findElem n' xs
where findElem num =
head .
fst .
foldr (\x (acc,iterator) ->
if iterator /= 0
then (x : acc,iterator - 1)
else (acc,iterator))
([],num)
n' = length xs - n
Upvotes: -1
Reputation: 48611
Think about a few things.
What type should init_val
have?
What do you need to do with g
? g
is the trickiest part of this code. If you've ever learned about continuation-passing style, you should probably think of both init_val
and g
as continuations.
What does x
represent? What will you need to do with it?
I wrote up an explanation some time ago about how the definition of foldl
in terms of foldr
works. You may find it helpful.
Upvotes: 1