Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seer: A Monadic Scry Interface #33

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
107 changes: 107 additions & 0 deletions UIPS/SEER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
title: Seer
description: A monadic scry interface.
author: ~fodwyt-ragful, ~mastyr-bottec
status: Draft
type: Standards Track
category: Kernel, Hoon
created: 2023-10-04
---

## Abstract

Seer is a monadic scry interface which allows application developers to
read from the namespace without using dotket (`.^`) or its virtual
Nock operator 12. Once we remove Nock 12, _all_ code in the system
can take advantage of persistent memoization.

## Motivation

dotket and Nock 12, which dotket compiles to, makes Nock _not_ referentially
transparent. By consequence, memoization is less effective.

In the interest of removing dotket and Nock 12 in the future, a replacement must
first be supplied. The replacement should attempt to be as ergonomic as dotket.

## Specification

Here's a Gall agent snippet that scries with `.^`:
```hoon
++ on-poke
|= [m=mark v=vase]
^- (quip card _this)
=/ foo-result .^ @da /cx/(now)/foo
:: do something with foo-result...
[~ this]
```

Here's the same Gall agent snippet that scries with `seer` in the
continuation style:
```hoon
++ gear :: gall seer
|* a=mold
(seer vase a)
++ on-poke
|= [m=mark v=vase]
^- (gear (quip card _this)) :: (seer vase (quip card _this))
:+ %scry /cx/(now)/foo |= foo=vase
=/ foo-result !<(@ foo)
:: do something with foo-result...
[%done ~ this]
```

Here's an example of composing `seer` values with monadic bind:
```hoon
++ foo ^- (seer vase @) !! :: /foo
++ bar ^- (seer vase @) !! :: /bar
++ on-poke
|= [m=mark v=vase]
=* r (quip card _this)
^- (gear r)
=/ bind (rapt vase r)
;< foo=@ bind foo
;< bar=@ bind bar
[%done ~ this(some-state (add foo bar))]
```

A `seer` is the type of programs that scry:
```hoon
++ seer
|* [r=mold a=mold]
$~ [%done *a]
$% [%done p=a]
[%scry p=path k=$-(r (seer r a))]
==
```

See the reference implementation for the monadic bind (`rapt`).

## Rationale

We believe `seer` degrades ergonomics only slightly while removing an ugly
wart that has plagued Urbit since its birth.

12 destroys the referential transparency of Nock, making every computation
dependent on a hidden context. This prevents transparent, system-wide
persistent memoization (among other things).

## Backwards Compatibility

The `seer` scry system is intentionally incompatible with the `.^` scry system.

We will support both scry styles for some time before deprecating and eventually
removing `.^`. In the meantime, we shall provide a wrapper library which accepts
an agent written in the `seer`-style and produces an agent that scries in the
`.^`-style.

## Reference Implementation

https://github.com/urbit/urbit/pull/6842

## Security Considerations

A simpler system is a more secure system.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).