Range Over Iterators in Idris
On this page
Our program will demonstrate how to range over iterators using Idris. Here’s the full source code.
module Main
import Data.List
import Control.Monad
data List a = MkList { head : Maybe (Element a) }
data Element a = MkElement { next : Maybe (Element a), val : a }
push : a -> List a -> List a
push v (MkList Nothing) = MkList (Just (MkElement Nothing v))
push v (MkList (Just tail)) = MkList (Just (MkElement (Just (MkElement Nothing v)) (val tail)))
-- All returns a Stream, which is a special structure in Idris
allElements : List a -> Stream a
allElements (MkList Nothing) = repeat []
allElements (MkList (Just el)) = iterate (\e => fmap next e) (Just el) >>= fmap val
-- Function returning a Stream of Fibonacci numbers
genFib : Stream Int
genFib = let fibs = 1 :: 1 :: zipWith (+) fibs (tail fibs) in streamFromList fibs
main : IO ()
main = do
let lst = push 23 $ push 13 $ push 10 $ MkList Nothing
putStrLn "List Elements:"
sequence_ $ mapM_ (putStrLn . show) (streamTake 3 (allElements lst))
putStrLn "Fibonacci Numbers:"
sequence_ $ mapM_ (putStrLn . show) (streamTakeWhile (< 10) genFib)
Explanation
List and Element Definitions
We define a List
as a structure that may contain a head, which is an Element
. The Element
itself contains a value and may point to the next Element
.
Push Function
The push
function adds a new element to the list. If the list is empty it creates a new element, else it adds it as the next element of the last one.
AllElements Function
allElements
returns a Stream
of values in the List
, where Stream
is an Idris construct suited for lazy evaluation. We use iterate
to traverse through the elements, and fmap
to collect the values.
Fibonacci Generator
The genFib
function generates an infinite Stream
of Fibonacci numbers, utilizing Idris’s ability to handle infinite structures through lazy evaluation.
Main Function
In the main
function, we:
- Create a list and add elements to it.
- Print the elements in the list.
- Print Fibonacci numbers less than 10.
By using sequence_
, we ensure that the IO operations (printing in this case) are executed in sequence.