I'm new to Haskell, and this is one of the more interesting programs I've made with it so far. I understand there are already solutions to this problem that use much less code, but to me this one seems fairly intuitive. Are there any ways I can improve this code to be more readable or efficient?
fib :: Int -> [Integer]
fib n = (n-1) `replicate` 0 !: 1 ++ (+) `zipPoly` repFor tail (fib n) n
(!:) :: [x] -> x -> [x]
[] !: a = [a]
(l:ls) !: a = l : ls !: a
zipPoly :: (x -> x -> x) -> [[x]] -> [x]
zipPoly _ [] = []
zipPoly _ [a] = a
zipPoly f (a:b:c) = zipPoly f $ zipWith f a b : c
repFor :: (x -> x) -> x -> Int -> [x]
repFor _ _ 0 = []
repFor f a n = a : repFor f (f a) (n-1)
main = do
s <- getLine
putStrLn "Starting..."
putStr $ unlines $ map show $ fib (read s :: Int)
Explanations of functions:
fib n
is a list containing then
-bonacci numbers, starting withn-1
zeros and then a one.list !: elem
concatenateselem
to the end oflist
.zipPoly func lists
is equivalent tozipWith
but with more than two lists.repFor func start amount
is a list of lengthamount
where the first element isstart
and every element after it isfunc
applied to the element before it ([x, f x, f (f x), f (f (f x))...]
).
1 Answer 1
Spacing! Separate function definitions with blank lines.
I'd use a, b, c
for type variables and x, y, z
for variables.
A .
looks cleaner than a $
.
putStr . unlines . map show . fib $ read s :: Int
I would add another pair of parentheses to make the order of application absolutely obvious.
(l:ls) !: a = l : (ls !: a)
For similar reasons, I prefer the following.
fib n = fibBase ++ zipPoly (+) fibTails
where fibBase = replicate (n-1) 0 ++ [1]
fibTails = repFor tail (fib n) n
I'd use cs
for the remainder of the list instead of c
. Perhaps a where
helps, too.
zipPoly f (a:b:cs) = zipPoly f $ c:cs
where c = zipWith f a b
zipPoly
needs the associativity of f
, if I'm not mistaken. Perhaps its worth a comment.
Perhaps use a fold
?
zipPoly f [] = []
zipPoly f (xs:xss) = foldl (zipWith f) xs xss
Don't reinvent the wheel too much :). Use Hoogle to search for a function using its signature.
For example, !:
is snoc
. Since you only use it once, I'd replace it with a ++
. Similarly, repFor f x0 n
is take n . iterate f $ x0
.
-
\$\begingroup\$ I never knew what
foldl
andfoldr
meant before. Thanks! \$\endgroup\$fluffyyboii– fluffyyboii2021年04月29日 20:40:53 +00:00Commented Apr 29, 2021 at 20:40
Explore related questions
See similar questions with these tags.