Skip to content

Exercise Idea: composite-resistors #1608

Open
@sshine

Description

@sshine

This exercise is proposed in the context of the Haskell track, but I'm posting it here because I like the idea of sharing exercise ideas across, and monoid abstractions exist in other languages, too. In the process of porting resistor-color-trio in exercism/haskell#869, it occurred to me that resistors are monoids in two ways:

When you put them in series, they form an additive monoid (resistance adds up) with (black, black, black), better known as a wire, as the identity resistor. And when you put them in parallel, you don't exactly get a multiplicative monoid, since n resistors in parallel add up like 1/R = 1/R₁ + 1/R₂ + ... + 1/Rₙ. What's the identity resistor for a parallel circuit?

It isn't a wire, since then the current would follow the path of least resistance, which would always end up being the wire. A neutral resistor in a parallel circuit is any non-conductive material with infinite resistance. For example, my willingness to code in another language than Haskell.

Putting resistors in series and in parallel is neat in practice for making non-standard resistors or when you run out of a certain kind of resistor.

Haskell has some machinery for dealing with types that are monoids in more than one way: while one can define instance Monoid (Sum Resistor) where ... for the built-in Sum type, it seems necessary to define one's own Parallel type and make instance Monoid (Parallel Resistor) where ... instead.

Having this exercise in succession of resistor-color-trio leads to interesting thoughts:

  • The data type Resistor is given as a newtype wrapper around (Color, Color, Color).
  • But that means there is no constructor for a resistor with infinite resistance.
  • But that means some composite resistors don't have such a representation:
    let   r50 = Resistor (Green, Black, Black)
        r1000 = Resistor (Brown, Black, Orange)
        r1050 = getSum (Sum r50 <> Sum r1000)
    
    r1050 == Resistor (???)
  • But that's okay, because this representation has another bad property:
    let ten1 = Resistor (Brown, Black, Black)
        ten2 = Resistor (Black, Brown, Brown)
    
    ohms ten1 == ohms ten2 -- True
    ten1      == ten2      -- False
    (We don't compare Resistors for equality in -trio, so we live with it there.)
  • A necessary part of this exercise would then be to refactor the representation of -trio.
  • This is an excellent opportunity for property-based tests of monoidal laws.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions