# The \`todo\` function

**URL:** <https://discourse.haskell.org/t/the-todo-function/8986>\
**Category:** Links\
**Created:** [March 7, 2024, 4:26pm UTC](https://discourse.haskell.org/t/the-todo-function/8986 "2024-03-07T16:26:28Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![MangoIV](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mangoiv/32/3519_2.png) [@MangoIV](https://discourse.haskell.org/u/MangoIV)\
**Post date:** [March 7, 2024, 4:26pm UTC](https://discourse.haskell.org/t/the-todo-function/8986/1 "2024-03-07T16:26:28Z")

</div>

I hope to add the `todo` function to the GHC’s `base` `Prelude` and hence opened a proposal with the core libraries committee:

> <https://github.com/haskell/core-libraries-committee/issues/260>
>
> Dear Haskell core library committee.
> 
> Currently there are multiple ways of des…cribing something as unimplemented
> \- undefined
> \- error "not implemented yet" 
> \- various other, similar functions from external libraries, such as the ones in alternative preludes like \`Relude\` \[placeholders\](https://hackage.haskell.org/package/placeholders-0.1/docs/Development-Placeholders.html#v:todo) or \[the todo package\](https://hackage.haskell.org/package/todo-0.2.0.3/docs/Debug-Todo.html)
> \- typed holes
> 
> All of these have problems: 
> 
> 1. Problems of the functions currently in \`base\`: 
> \- \`undefined\`: 
> - doesn't give you a warning if it remains in code
> - doesn't read as "this is open, I will definitely implement it soon"
> - a lot to type for "please compiler, be quiet for the second, I will come back to this" 
> \- \`error\`: 
> - also doesn't give you a warning if it remains in code
> - may read as "this is open, I will definitely implement it soon" \*but\* this is a lot to type
> - even more to type for "please compiler, be quiet for the second, I will come back to this", sometimes even needs paranthesis 
> 2. external dependencies:  
> \- just for doing a quick debugging \`todo\`, it doesn't seem worth adding an alternative \`Prelude\` or even add a dependency just for the sake of this
> 3. typed holes 
> \- they are, by default, errors, not warnings
> \- they are very noisy (by default they produce a lot of output)
> \- they are slow (by default) 
> 
> That's why propose a function \`todo\` that has the following properties: 
> \- has a warning annotation \`"todo remains in code"\` in group \`x-todo\` so that it can be used with \`WError\` for e.g. CI
> \- has the same type as \`undefined\` 
> \- gets (re)exported by \`base:Prelude\` 
> \- is to be used whenever there is a place in the code where we want to temporary fill holes
> \- the warning message is not fixed as shown in the example implementation and may be adjusted, similar things hold for the documentation
> 
> The implementation would be as follows: 
> 
> \`\`\`haskell
> {-# LANGUAGE ImplicitParams #-}
> {-# LANGUAGE MagicHash #-}
> {-# OPTIONS\_GHC -Wall #-}
> 
> module Todo (todo) where
> 
> import GHC.Base (raise#, TYPE, RuntimeRep)
> import GHC.Exception (errorCallWithCallStackException)
> import GHC.Stack (HasCallStack)
> 
> {- | 'todo' indicates unfinished code. 
> 
> It is to be used whenever you want to indicate that you are missing a part of 
> the implementation and want to fill that in later. 
> 
> The main difference to other alternatives like typed holes and 'undefined' 
> or 'error' is, this does not throw an error but only emits a warning. 
> 
> Similarly to 'undefined', 'error' and typed holes, this will throw an error if 
> it is evaluated at runtime which can only be caught in 'IO'. 
> 
> This is intended to \*never\* stay in code but exists purely for signifying
> "work in progress" code. 
> 
> ==== \_\_Examples\_\_
> 
> @
> superComplexFunction :: 'Maybe' a -\> 'IO' 'Int'
> \-- we already know how to implement this in the 'Nothing' case
> superComplexFunction 'Nothing' = 'pure' 42
> \-- but the 'Just' case is super complicated, so we leave it as 'todo' for now
> superComplexFunction ('Just' a) = 'todo'
> @
> \-}
> todo :: forall {r :: RuntimeRep} (a :: TYPE r). (HasCallStack) =\> a
> todo = raise# (errorCallWithCallStackException "Prelude.todo" ?callStack)
> {-# WARNING in "x-todo" todo "todo remains in code" #-}
> \`\`\`
> 
> try it out in a separate module, as such: 
> 
> \`\`\`haskell
> module TodoExample where
> 
> import Todo
> 
> superComplexFunction :: Maybe a -\> IO Int
> \-- we already know how to implement this in the 'Nothing' case
> superComplexFunction Nothing = pure 42
> \-- but the 'Just' case is super complicated, so we leave it as 'todo' for now
> superComplexFunction (Just a) = todo
> \`\`\`
> 
> This implementation will work from \`\>= ghc981\`
> 
> 
> Impact: 
> 
> on \[hoogle\](https://hoogle.mangoiv.com/?q=todo) I currently find 4 functions which this would break, two of which have similar semantics to this one, making it improbable that they will be found in code out there. 
> 
> I will obviously run a proper impact assessment though. 
> 
> Also look at: 
> \[rust std's \`todo!\` and \`unimplemented!\` macros\](https://doc.rust-lang.org/std/macro.todo.html)
> 
> Rendered docs: 
> !\[rendered docs without expanded Examples\](https://github.com/haskell/core-libraries-committee/assets/40720523/eea71f3b-97a1-4dd5-b687-a1fc4eeb0779)
> !\[rendered docs with expanded Examples\](https://github.com/haskell/core-libraries-committee/assets/40720523/ff4e4ccb-4fba-4fc1-a2b1-1bacd389d3f4)
> 
> How it looks, loading a module using \`todo\` into \`GHCi\`:
> 
> !\[screenshot of terminal showing how it looks to load a module using the \`todo\` function\](https://github.com/haskell/core-libraries-committee/assets/40720523/83ee9fdb-19e3-41f1-8aea-4fa495365ec7)

Please do not hesitate to leave a heart and comment if you have something to say on this topic.

If you find any errors or weirdnesses in the proposal itself, please comment _under this post_, not the proposal.

Thank you!
