Skip to content

Commit

Permalink
fix runListT (#89)
Browse files Browse the repository at this point in the history
* stack-safe foldl

* name TCOd foldl fodlRec

* add stack-safe foldl'

* Adapt runListT from Haskell's List.Transformer

* ListT examples

* simplify runListT

Unnecessary use of `void action`.

* add runListTRec and use in examples
  • Loading branch information
matthewleon authored and paf31 committed Mar 30, 2017
1 parent e680771 commit cc045ea
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/Control/Monad/List/Trans.purs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ module Control.Monad.List.Trans
, prepend
, prepend'
, repeat
, runListT
, runListTRec
, scanl
, singleton
, tail
Expand Down Expand Up @@ -70,9 +72,14 @@ data Step a s
| Skip (Lazy s)
| Done

-- | Run a computation in the `ListT` monad.
runListT :: forall f a. ListT f a -> f (Step a (ListT f a))
runListT (ListT fa) = fa
-- | Drain a `ListT`, running it to completion and discarding all values.
runListT :: forall f a. Monad f => ListT f a -> f Unit
runListT = foldl' (\_ _ -> pure unit) unit

-- | Drain a `ListT`, running it to completion and discarding all values.
-- | Stack safe: Uses tail call optimization.
runListTRec :: forall f a. MR.MonadRec f => ListT f a -> f Unit
runListTRec = foldlRec' (\_ _ -> pure unit) unit

-- | The empty list.
nil :: forall f a. Applicative f => ListT f a
Expand Down
37 changes: 37 additions & 0 deletions test/Example/List.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module Example.List where

import Prelude
import Data.Array as A
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Class (liftEff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Control.Monad.List.Trans (ListT, runListTRec, iterate, takeWhile)
import Control.MonadZero (guard)

-- based on http://hackage.haskell.org/package/list-transformer
logList :: forall eff.
ListT (Eff (console :: CONSOLE | eff)) String
-> Eff (console :: CONSOLE | eff) Unit
logList l = runListTRec do
liftEff $ log "logging listT"
str <- l
liftEff $ log str

-- based on https://wiki.haskell.org/ListT_done_right#Sum_of_squares
sumSqrs :: forall eff.
Int
-> ListT (Eff (console :: CONSOLE | eff)) Unit
sumSqrs n = do
let
nats = iterate (add one) zero
squares = takeWhile (_ <= n) $ map (\x -> x * x) nats
x <- squares
y <- squares
liftEff $ log ("<" <> show x <> "," <> show y <> ">")
guard $ x + y == n
liftEff $ log "Sum of squares."

main :: forall eff. Eff (console :: CONSOLE | eff) Unit
main = do
logList $ A.toUnfoldable ["one", "two", "three"]
runListTRec $ sumSqrs 10
2 changes: 2 additions & 0 deletions test/Test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Example.State as State
import Example.StateEff as StateEff
import Example.Writer as Writer
import Example.RWS as RWS
import Example.List as List

main :: Eff (console :: CONSOLE) Unit
main = do
Expand All @@ -20,3 +21,4 @@ main = do
StateEff.main
Writer.main
RWS.main
List.main

0 comments on commit cc045ea

Please sign in to comment.