Code assignment
Long story short, I had an interview with Modus Create last month, we discussed possible implementation of such an assignment (I simplified it for you):
Given a list of numbers, return a sublist with reached threshold of sum its elements.
I think an interviewer made his mind once I started talking about comonads. I proposed to demonstrate how I would solve this kata, but it doesn’t seem they were particularly interested. This code snippet has been shown as a proper solution:
threshold :: [Integer] -> Integer -> Maybe [Integer]
threshold (x : xs) v | v < 0 = Just []
threshold [] _ = Nothing
threshold (x : xs) v = (x :) <$> threshold xs (v - x)
Well, this solution is fine, you can make it work properly after several iterations but… its core design is bad. Whenever I need to come back to this piece I have to be very careful, probably relying on some tests - so that it’s highly likely would be cheaper just to rewrite everything from scratch rather than trying to enhance it.
In Я we beat this type of complexity with effects.
Computation units
Let’s forget about datastructures and try to describe action units in whole computation.
Add a current item to stateful counter and result (State):
`yuk____` Apply `ha` State `hv__` Event `hv_` get `ha` subtract x `ha_` Scope `hv` at @Integer
`lu__'yp` Apply `ha` State `hv__` Event `hv_` get `ha` that `ha` push x `ha_` Scope `hv` at @(List Integer)
If threshold has been reached - finish (Stops):
limit (These counter result) = if 0 >= counter then Break result else Valid counter
But those expressions above have different effects… so let’s joint them:
Stops (List Integer) `JNT` State (List Integer `P` Integer)
So that we can use them together:
step x = intro @(Stops (List Integer) `JNT` State (List Integer `P` Integer)) Unit
`yuk____` Apply `ha` State `hv__` Event `hv_` get `ha` subtract x `ha_` Scope `hv` at @Integer
`lu__'yp` Apply `ha` State `hv__` Event `hv_` get `ha` that `ha` push x `ha_` Scope `hv` at @(List Integer)
`yok____` Check `ha` limit
Applying this computation step one after another while traversing any datastructure:
test v items = items
`yokl` Forth `ha` Run `ha` step
`he'he'hv___` empty @List `lu` v
`yi__` print `la` No `hu` print "Not found!"
Finally running it and get proper results:
test 15 `ha` is @(Nonempty List Integer) `hv` [1,2,6,6,4,3,6,8,4,5,4,9,0]
test 15 `ha` is @(Nonempty List Integer) `hv` [15]
test 15 `ha` is @(Nonempty List Integer) `hv` [1]
Full source code is available here.
But it’s more code…
You can argue that I have to write more code in order to reach the same functionality - and you are absolutely right! However, real world programming is far from code golf and we cannot rely on primitive methods on a long run by one single reason:
Simplicity doesn’t not scale!