Skip to content

Instantly share code, notes, and snippets.

@xaviervia
Last active June 4, 2017 00:57
Show Gist options
  • Save xaviervia/193a233a6f271776261d7806302989fe to your computer and use it in GitHub Desktop.
Save xaviervia/193a233a6f271776261d7806302989fe to your computer and use it in GitHub Desktop.
Simple Cell recomputation
data Recomputation a = Same a
| Different a
data Cell : Type where
MkCell : Eq b => (computation : (a -> b)) -> (value : Recomputation (a, b)) -> Cell
recompute : Cell -> Cell
recompute (MkCell computation (Same x)) = MkCell computation (Same x)
recompute (MkCell computation (Different (a, b))) =
let
result = computation a
in
case result == b of
True => MkCell computation (Same (a, b))
False => MkCell computation (Different (a, result))
testCell : Cell
testCell = MkCell negate (Different (1, 2))
nextCell : Cell
nextCell = recompute testCell
-- Which results in `MkCell negate (Different (1, -1))`
@xaviervia
Copy link
Author

I’m just noticing a couple of things about the languages:

  • Idris is pretty terse, but it has some trivial repetition, in this case because of case splitting between constructors.
  • JavaScript is the shortest but because it ends up being just a bunch of functions, without any data structure specification. It’s also surprisingly easy, since there are no restrictions to bear in mind. Like play-doh.
  • Ruby is verbose and it reads a little clunky when declaring classes, but can be used to good effect for this.

@xaviervia
Copy link
Author

Obviously the ideal would be that Same and Different are guaranteed by the type to be valid, so that you can’t construct a Same cell if (computation input) != output.

@xaviervia
Copy link
Author

My Java is rusty:

interface Computable {
  public Object compute (Object argument);
}

abstract class Cell {
  private Computable computation;
  private Object input;
  private Object output;

  public Computable getComputation () {
    return computation;
  }

  public Object getInput () {
    return input;
  }

  public Object getOutput () {
    return output;
  }
}

class SameCell extends Cell {
  public SameCell (Object input, Object output, Computable computation) {
    this.input = input;
    this.output = output;
    this.computation = computation;
  }

  public Cell compute () {
    return this;
  }
}

class DifferentCell extends Cell {
  public DifferentCell (Object input, Object output, Computable computation) {
    this.input = input;
    this.output = output;
    this.computation = computation;
  }

  public Cell compute () {
    Object result = this.computation.compute(this.input);

    if (result == this.output) {
      return new SameCell(this.input, this.output, this.computation);
    } else {
      return new DifferentCell(this.input, result, this.computation);
    }
  }
}

@xaviervia
Copy link
Author

Modern PHP (super rusty too):

<?
$recompute = function ($cell) {
  if ($cell['different'] == true) {
    $result = $cell['computation']($cell['input']);

    if ($result == $output) {
      return array(
        'different' => false,
        'computation' => $cell['computation'],
        'input' => $cell['input'],
        'output' => $cell['output']
      );
    } else {
      return array(
        'different' => true,
        'computation' => $cell['computation'],
        'input' => $cell['input'],
        'output' => $result
      );
    }
  } else {
    return $cell;
  }
};

$testCell = array(
  'different' => true,
  'computation' => function ($int) { return -$int; },
  'input' => 1,
  'output' => 2
);
$nextCell = $recompute($testCell);
$finalCell = $recompute($nextCell);

var_dump($testCell);
var_dump($nextCell);
var_dump($finalCell);
?>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment