You're definitely on the right track here for producing good Haskell code, assuming you're intentionally avoiding Prelude functions in favor of exercising other skills!
The very first thing I would change is the order of arguments in your myFold
function (and by extension go
), i.e., pass the function to map over the list in the first position. This can help you be terse when calling it elsewhere in your code. For instance, consider these two trivial definitions of the same identity function.
listid :: [a] -> [a]
listid as = myFold as (:[])
listid' = myFold' (:[]) -- Implies an instance of myFold w/ arguments flipped
The second definition is written in pointfree style. This is considered good practice (in moderation) due to its emphasis on composing functionality over moving data around.
The next thing I would address is hiding your helper function go
by making it locally defined in myFold
.
myFold f as = go ...
where go f as acc = ...
This has a few benefits.
- If you're writing a library module here by default
go
will end up being exported to all of your users. Since this is an anonymous helper function, you probably don't want that.
- Because again this is a one-shot helper function, locally defining it for
myFold
keeps it close to where it's used as opposed to floating around the top-level elsewhere.
That's about as idiomatic as you'll get without using Prelude functions. It is good to note however that your function is the composition of concat
and map
, and reusing functions from the Prelude is almost always better for readability.