# Implementing Unsure Calculator in 100 lines of Haskell

DevFeed: [Implementing Unsure Calculator in 100 lines of Haskell](<https://devfeed.tech/articles/implementing-unsure-calculator-in-100-lines-of-haskell-27917.md>)

Original publisher: [Read original article](<http://alt-romes.github.io/posts/2025-04-25-unsure-calculator-in-100-lines-of-haskell.html>)

Published: 2025-04-25T00:00:00Z

Content type: tutorial

Language: en

Sources: [Romes' Musings](<https://devfeed.tech/sources/romes-musings.md>)

Topics: [Haskell](<https://devfeed.tech/topics/haskell.md>), [Development](<https://devfeed.tech/topics/development.md>), [math](<https://devfeed.tech/topics/math.md>)

Tags: [article](<https://devfeed.tech/tags/article.md>), [expression](<https://devfeed.tech/tags/expression.md>), [haskell](<https://devfeed.tech/tags/haskell.md>), [list](<https://devfeed.tech/tags/list.md>), [monad](<https://devfeed.tech/tags/monad.md>), [numbers](<https://devfeed.tech/tags/numbers.md>), [operations](<https://devfeed.tech/tags/operations.md>), [range](<https://devfeed.tech/tags/range.md>)

## AI overview

This tutorial implements an Unsure Calculator in Haskell. It introduces a range operator for uncertain values, models calculations with a probability monad and normal distributions, samples results using pseudo-randomness, and builds an embedded calculator expression language.

## Source excerpt

Contents 1 Unsure Calculator 1.1 Sampling it up 1.2 Calculator Expressions 1.3 Showing up 1.4 Conclusion 1 Unsure Calculator The recently trendy Unsure Calculator makes reasoning about numbers with some uncertainty just as easy as calculating with specific numbers. The key idea is to add a new "range" operator (written ~) to the vocabulary of a standard calculator. The range x~y denotes that a real value is uncertain, but we are 95% sure that it falls between x and y1. Reading the notation is easy: when you see 10~15, you say: "ten to fifteen". Arithmetic operations and friends (e.g. sin, or log) transparently operate on ranges and literal numbers alike. Calculation results in a plot with a range of values that the input expression can take, and with what frequency. The motivation behind the original article is neat, so I'll just recommend you read it there to learn how and why you'd use such a calculator. Here's a real life example they used: 1400~1700 * 0.55~0.65 - 600~700 - 100~200 - 30 - 20 Now, let's implement it. 1.1 Sampling it up Summon a probability monad from the void2. data Dist a where Return :: a -> Dist a Bind :: Dist b -> (b -> Dist a) -> Dist a Normal :: Double -> Double -> Dist Double instance Monad Dist where (>>=) = Bind instance Applicative Dist where pure = Return; (<*>) = ap instance Functor Dist where fmap = liftM The monad instance is free: pure = Return and (>>=) = Bind. The Normal constructor denotes a normal distribution given the standard deviation and mean. With do-notation we can easily construct a complex tree mixing Returns, Binds, and Normals. For instance: d = do s <- Normal 0 1 return (5 + s) desugars to d = Bind (Normal 0 1) (\s -> Return (5 + s)) Then, embue meaning onto a Dist a by allowing an a to be sampled according to the distribution the Dist represents. We use StdGen from random as a source of uniform pseudo-randomness: sample :: StdGen -> Dist a -> a sample g d = case d of Return x -> x Normal mean std_dev -> n1 * std_dev