-
Notifications
You must be signed in to change notification settings - Fork 3
Presentation 20230802 tllhug yuldsl progress report
Miao, ZhiCheng edited this page Aug 1, 2023
·
10 revisions
⚠ This file is automatically generated from this org file using this script.
The exported presentation can be accessed via this githack link.
REVISIONS:
Date | Notes |
2023-08-02 | Tallinn HUG First Meetup Talk. |
- What is YulDSL and why?
- “Evaluating Linear Functions to Symmetric Monoidal Categories” ☠.
- Linear Haskell in brief.
- What is yolc?
- Yul is an intermediate language designed to support different backends.
- But for now, Yul is tightly coupled with Solidity as its frontend language and EVM (Ethereum Virtual Machine) as its backend.
- YulDSL is a DSL for Yul.
-- from 'base' library:
-- | A class for categories. Instances should satisfy the laws
--
-- [Right identity] @f '.' 'id' = f@
-- [Left identity] @'id' '.' f = f@
-- [Associativity] @f '.' (g '.' h) = (f '.' g) '.' h@
--
class Category cat where
-- | the identity morphism
id :: cat a a
-- | morphism composition
(.) :: cat b c -> cat a b -> cat a c
-- from 'linear-smc' library
class Category k where
type Obj k :: Type -> Constraint {-<-}
id :: Obj k a => a `k` a
(∘) :: (Obj k a, Obj k b, Obj k c)
=> (b `k` c) -> (a `k` b) -> a `k` c
data YulCat a b where
-- ...
YulId :: forall a. YulO2 a a => YulCat a a
YulComp :: forall a b c. YulO3 a b c => YulCat c b -> YulCat a c -> YulCat a b
-- ...
YulApFun :: forall a b. YulO2 a b => Fn a b -> YulCat a b
YulITE :: forall a . YulO1 a => YulCat (BOOL, (a, a)) a
YulMap :: forall a b. YulO2 a b => YulCat a b -> YulCat [a] [b]
YulFoldl :: forall a b. YulO2 a b => YulCat (b, a) b -> YulCat [a] b
-- ...
YulNot :: YulCat BOOL BOOL
YulAnd :: YulCat (BOOL, BOOL) BOOL
YulOr :: YulCat (BOOL, BOOL) BOOL
YulNumAdd :: forall a. YulNum a => YulCat (a, a) a
YulNumNeg :: forall a. YulNum a => YulCat a a
-- ...
YulSGet :: forall a. YulVal a => YulCat ADDR a
YulSPut :: forall a. YulVal a => YulCat (ADDR, a) ()
- “It can be done in Rust.”™
- Compatible implementations of the DSL in different language can be a foundation for an interoperable module system between them.
- Promote Haskell an advanced alternative to Solidity to build on EVM.
- Making a case that we should build fewer new languages when some advanced language, such as Haskell, is well suited to provide eDSL to new problem domains.
- Building smart contracts at Superfluid using YulDSL.
Bernardy, Jean-Philippe, and Arnaud Spiwack. “Evaluating linear functions to symmetric monoidal categories.”
- This is also called “point-free style”.
- However this categorical language is really hard for (normal) human brains.
- The “open semicolon” notation is akin to what “(,)” is in Haskell.
- The familiar Latin letters are so-called “variables” that allow human brain to “delimit” its thinking patterns, in order to understand or construct such program “more naturally.”
Indeed, every linear function can be interpreted in terms of an smc. This is a well known fact, proven for example by Szabo [1978, Ch. 3] or Benton [1995].
- Linear functions are the “frontend language” human can naturally program with.
- SMC is the “backend language” that is compositional; and compositionality is good for:
- program reusability,
- compositionally correct methodology (Conal Elliot) for program correctness,
- etc.
A function f is linear if: when its result is consumed exactly once, then its argument is consumed exactly once.
- linearity over the arrow:
%1 ->
- Linear polymorphism:
forall w. a %w -> b
- Status: experimental and with limitations.
-
Prelude.Linear
as a linear replacement forPrelude
. - Additional primitives specific for programming linear functions:
Consumable
,Moveable
,Unrestricted
, etc. - Some functions may require
-XImpredicativeTypes
additionally.
-- | A port represents an input or an output of type @a@ of a morphism in the SMC.
data P k r a
-- | Encode a morphism in the SMC to linear function from port @a@ to port @b@
encode :: O3 k r a b => (a `k` b) -> P k r a %1 -> P k r b~
-- | Decode a linear function from port @a@ to port @b@ to its morphism in the SMC.
decode :: forall a b k con.
( con (), con ~ Obj k, Monoidal k, con a, con b
, forall α β. (con α, con β) => con (α, β)
)
=> (forall r. Obj k r => P k r a %1 -> P k r b)
-> a `k` b
(taken from a Tweag blog post)
- Define your DSL as a categorical language.
- Define SMC instances for your DSL:
instance Category YulCat where type Obj YulCat = YulObj id = YulId (∘) = YulComp instance Monoidal YulCat where (×) = YulProd unitor = YulCoerce unitor' = YulCoerce assoc = YulCoerce assoc' = YulCoerce swap = YulSwap instance Cartesian YulCat where dis = YulDis dup = YulDup
- Define additional linear combinators for your domain.
- Profit.
rangeSum :: Fn (UINT256 :> UINT256 :> UINT256) UINT256
rangeSum = defun "rangeSum" \(a :> b :> c) ->
dup2P a & \(a, a') ->
dup2P b & \(b, b') ->
dup2P c & \(c, c') ->
dup2P (a + b) & \ (d, d') ->
mkUnit a' & \(a', u) ->
a' + ifThenElse (d <? c) (apfun rangeSum (d' :> b' :> c')) (yulConst 0 u)
-- | ERC20 transfer function (no negative balance check for simplicity).
erc20_transfer :: Fn (ADDR :> ADDR :> UINT256) BOOL
erc20_transfer = defun "transfer" \(from :> to :> amount) ->
(copyAp amount
(\amount -> passAp from erc20_balance_of & \(from, balance) ->
erc20_balance_storage from <== balance - amount)
(\amount -> passAp to erc20_balance_of & \(to, balance) ->
erc20_balance_storage to <== balance + amount)) &
yulConst true
nix-shell$ yolc -h yolc, the YulDSL commandline transpiler. Usage: yolc [options] yol_module_spec... -m [output_mode] Valid output modes: show, plantuml, yul (default) -h Display this help and exit -v Output more information about what is going on yol_module_spec: {package_path:}module_name{[symbol...,]} where 1) both package_path and symbol list is optional, 2) default package_path is current working directory (/home/hellwolf/Projects/my/yul-dsl-monorepo), 3) and default symbol is 'defsym' (TODO, use object instead).
!NOTE!: the work is still in its early stage.
- Since SMC is well suited for visually programming your program formally, so does YulDSL.
- Arrow and its
proc
sugar notation also offer a way of wiring computational graphs. - Traced monoidal category provides an additional notion of feedback over SMC.
-
YulDSL has a richer structure than SMC, namely also cartesian closed.
- Cartesian closed category (CCC) is correspondent to lambda-calculus, hence normal Haskell function can even be translated to CCC.
- There are various compiling to categories projects. The most notable one is from Conal Elliott. But due to the production-readiness, it is harder to set it up.
Ship it!
Slides available from the wiki area of the yul-dsl-monorepo by searching “yuldsl progress”.