---
title: Reasoning by Analogy
teaser: A learning, problem solving, and debugging technique.
tags: elm,development,debugging
author: Joël Quenneville
published_on: 2025-03-27
---

**Reasoning by Analogy** is a powerful learning, problem-solving, and debugging technique. It's a
four-step process:

1. You have a question about something that you don't understand
2. Translate the question to something similar that you _do_ understand (called
   the analogue)
3. Solve the problem for this thing you understand
4. Translate the solution back to the original situation

While you may not think about this explicitly, you use this kind of reasoning
all the time when you leverage past experience to solve new problems.

![diagram of reasoning by analogy](https://images.thoughtbot.com/jq-reasoning-by-analogy/roNjrC63ScOPtdNrmdVO_reasoning-by-analogy.png)

## Grade school math

> Alice has 512 apples and Bob has 256 apples. How many do they have all
> together?

10-year-old you hates these kinds of problems. First of all, why do Alice and
Bob have so many apples??? 🍎🍏🍎🍏🍎

More importantly, what does the teacher want you to do here? You know it's math
but what operation do you need to do? Those big numbers are just making things
worse.

Time to simplify.

> Alice has 2 apples and Bob has 1 apple. How many do they have all together?

Intuitively, you count up on your fingers. Together Alice and Bob have 3 apples.
What did you just do? Oh, it's an addition problem!

Back to the original problem, you add the two big numbers together to get 768
apples. You're going to get a good grade on this one.

10-year-old you doesn't know it but you just used an analogy to reason your way
out of a problem that had you stuck.

## Parameterized Html and List types

Grown-up you is now a web developer. You've been picking up this new [Elm]
language. You're confused by this parameterized `Html` type. In particular,
you're trying to write a generic signature for this function.

```elm
type Msg = Increment | Decrement

someHtml : Html a
someHtml =
  div [onClick Increment] []
```

The compiler is having none of it and is giving you errors about your type being
too generic. It thinks the type should be `Html Msg`. How can a type be too
generic?!

It's hard to get the proper intuitions about these parameterized types. Wait,
that's not quite true. You have a good feel for the `List` type which is
parameterized. Can you use your knowledge of `List` to understand `Html`? Time
to construct an experiment!

```elm
someList : List a
someList =
  [Increment]
```

Aha! Same error about the type being too generic. That sort of makes sense
because you can see it is a hard-coded list of messages. If that's true then
what's the point of `List a`? A hardcoded `[1,2,3]` would _have_ to be `List Int`, and a hardcoded `["hello", "world"]` would _have_ to be `List String`.

Wait a minute, what about the empty list?

```elm
emptyList : List a
eptyList =
  []
```

That _does_ compile!

Again on further reflection that makes sense. The empty list is a valid `List String` and also a valid `List Int`, and also a valid `List Msg`. That would
mean that any function `someList : List a` _can only be an empty list_. Taking
this idea further, you wonder if having a more generic signature actually limits
the valid implementations. Could this idea also apply to your original HTML
problem?

Given that `Html Msg` means "some HTML with event handlers that emit `Msg`
values", what would be the equivalent of an empty list? Perhaps some HTML with
no event handlers?

```elm
staticHtml : Html a
staticHtml =
  div [] []
```

Oh look that compiles! It looks like you were right. Just like
`someList : List a` _must_ be empty, it looks like `someHtml : Html a` _must_ be
static!

You used your intuition about lists in combination with reasoning by analogy to
learn something new. Time to celebrate! 🎉

<aside class="info">Did you find this blog post because you're trying to learn about Elm's generic <code>Html a</code> type? I've got you! I put together a <a href="https://gist.github.com/JoelQ/98c5c6a17fd82d8ddd932a75eceb4276">list of exercises</a> that have you explore generics with types that feel more concrete such as <code>List a</code> and <code>Maybe a</code>. Use the reasoning by analogy techniques from this article to carry that learning over to <code>Html a</code>!
</aside>

## False analogies

Reasoning by analogy is a powerful learning and debugging technique but it has
one big weakness - **false analogies**.

It's important to be really careful in **step 2** where you find a similar
problem that you already understand. If your analogue is not really similar,
then your solution won't translate back correctly. This can lead you to wrong
conclusions!

Looking back at that grade-school math problem, what if you'd "simplified" the
problem to

> Alice has 2 apples and Bob has 1 apple. How many more does Alice have?

The solution here (subtraction) will *not* solve the original problem because
our simplified problem is no longer analogous to original.

If you're using reasoning by analogy as a debugging tool, make sure you can
reproduce the same bug with your analogue problem.

## More than just learning

Reasoning by analogy is a great tool for learning but it can apply to a lot of other situations too. I commonly use it for **debugging**, such as this [random generators stack overflow bug](https://thoughtbot.com/blog/elm-debugging-story), where I converted the problem to a more tractable function composition problem, figured out the problem there, and then backported the solution to the original random generator problem.

It's also really helpful as a **general problem solving** tool. When I get stuck writing complex JSON decoders, I will instead [convert the problem to a more intuitive Maybe problem](https://thoughtbot.com/blog/getting-unstuck-with-elm-json-decoders), solve it there, and then backport the solution to `Json.Decode`.

## Other types of reasoning

Reasoning by analogy has its roots in classical philosophy. There are some
other classical reasoning techniques including:

* Deductive reasoning (big picture -> details)
* Inductive reasoning (details -> big picture)
* Process of elimination

I have a whole article dedicated to using these [classical reasoning techniques for debugging](https://thoughtbot.com/blog/classical-reasoning-and-debugging), including a section on reasoning by analogy.

[Elm]: http://elm-lang.org/
