I wrote a function to find if a character is a duplicate in a string.
The way it is defined, the function when called isDuplicate 'b' "abbey" False it will return True.
How can it refactored to eliminate Bool as one of the arguments/parameters?
Defining a helper function will get the job done, but is that the only solution?
isDuplicate : Char -> String -> Bool -> Bool
isDuplicate xs word_ foundAlready =
case ( String.uncons word_, foundAlready ) of
( Nothing, _ ) ->
False
( Just ( first, rest ), _ ) ->
let
foundNow = Char.toLower first == xs
in
if foundNow && foundAlready
then True
else isDuplicate xs rest (foundNow || foundAlready)
Yes the usual pattern is to rename the function you have already to isDuplicateHelp and then make another function isDuplicate to call it with the initial value. External code calls the new isDuplicate, which doesn’t have the Bool argument.
Edit: so my point is that this is totally idiomatic and normal, I wouldn’t see any reason to look for another way.
You can also do this using List.foldl. Here’s how I would implement such a function:
peakCount max cur match =
if cur == max then max
else if match then cur + 1
else 0
isMulti: Int -> Char -> String -> Bool
isMulti count toFind findIn =
(String.toList findIn
|> List.foldl (\ch cur -> peakCount count cur (toFind == Char.toLower ch)) 0) == count
isDuplicate: Char -> String -> Bool
isDuplicate = isMulti 2
The peakCount function works by counting “Trues”: it will add one for every true until it hits max at which point it will always return max. If it get a false before getting to max, it resets and returns 0. The isMulti function looks for the specified character in the string, using List.foldl and the peakCount function to count that character in sequence. isDuplicate is just a specialization of isMulti. The nice thing about isMulti is that it’s no more difficult to find a sequence of 10 letters than it is to find a duplicate. The call would be: