Virtual meeting 2?

24 views
Skip to first unread message

Brian Gomes Bascoy

unread,
Mar 26, 2021, 3:09:29 AM3/26/21
to SeaHUG
Hey everyone!

Hope you're all doing well. I was wondering if there is general interest for a second virtual meeting, it's been a while since the last one :)

Cheers

Bryan Grounds

unread,
Mar 26, 2021, 3:24:38 AM3/26/21
to Brian Gomes Bascoy, SeaHUG
Definitely. It's been too long!

--
You received this message because you are subscribed to the Google Groups "SeaHUG" group.
To unsubscribe from this group and stop receiving emails from it, send an email to seattlehaskel...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/seattlehaskell/4439e123-9d77-4ca5-82c9-7df923c3d35bn%40googlegroups.com.

Michael Kerekes

unread,
Mar 26, 2021, 2:19:15 PM3/26/21
to Bryan Grounds, Brian Gomes Bascoy, SeaHUG

Brian

unread,
Mar 27, 2021, 1:46:23 PM3/27/21
to Michael Kerekes, Bryan Grounds, SeaHUG
Cool! What do you think about next Saturday? (April 3rd)

I have some Haskell stuff to show but it's quite simple, shouldn't take
more than 15 mins total to present.

Maybe we could also have some updates on the current state of Mana? :)



On Fri, 2021-03-26 at 11:19 -0700, Michael Kerekes wrote:
> That would be nice.
>
> On Fri, Mar 26, 2021 at 12:24 AM Bryan Grounds <bagr...@gmail.com>
> wrote:
>
> > Definitely. It's been too long!
> >
> > On Fri, Mar 26, 2021, 12:09 AM Brian Gomes Bascoy
> > <gomes...@gmail.com>
> > wrote:
> >
> > > Hey everyone!
> > >
> > > Hope you're all doing well. I was wondering if there is general
> > > interest
> > > for a second virtual meeting, it's been a while since the last
> > > one :)
> > >
> > > Cheers
> > >
> > > --
> > > You received this message because you are subscribed to the
> > > Google Groups
> > > "SeaHUG" group.
> > > To unsubscribe from this group and stop receiving emails from it,
> > > send an
> > > email to seattlehaskel...@googlegroups.com.
> > > To view this discussion on the web visit
> > > https://groups.google.com/d/msgid/seattlehaskell/4439e123-9d77-4ca5-82c9-7df923c3d35bn%40googlegroups.com
> > > <https://groups.google.com/d/msgid/seattlehaskell/4439e123-9d77-4ca5-82c9-7df923c3d35bn%40googlegroups.com?utm_medium=email&utm_source=footer
> > > >
> > > .
> > >
> > --
> > You received this message because you are subscribed to the Google
> > Groups
> > "SeaHUG" group.
> > To unsubscribe from this group and stop receiving emails from it,
> > send an
> > email to seattlehaskel...@googlegroups.com.
> > To view this discussion on the web visit
> > https://groups.google.com/d/msgid/seattlehaskell/CACsHsXhPUoP4pFR2Q7GVRjKnEUgQHsz7egq5-e5B8xm_5%3DBonw%40mail.gmail.com
> > <https://groups.google.com/d/msgid/seattlehaskell/CACsHsXhPUoP4pFR2Q7GVRjKnEUgQHsz7egq5-e5B8xm_5%3DBonw%40mail.gmail.com?utm_medium=email&utm_source=footer
> > >
> > .
> >

Bryan Grounds

unread,
Mar 27, 2021, 5:51:47 PM3/27/21
to Brian, Michael Kerekes, SeaHUG
Sounds good to me!

I've also been working on a peer to peer Dominion clone in Purescript that I'd be happy to talk about. I actually have some design questions I'd like to run by the group.

Bryan Grounds

unread,
Mar 31, 2021, 1:38:00 PM3/31/21
to SeaHUG
What video platform should we meet on?

Anyone else interested?

Brian Gomes Bascoy

unread,
Mar 31, 2021, 1:51:39 PM3/31/21
to Bryan Grounds, SeaHUG
I like Jitsi Meet: no login required, no weird proprietary plugins, and it only takes one click to create a new meeting room :)


Michael Kerekes

unread,
Mar 31, 2021, 1:59:43 PM3/31/21
to Brian Gomes Bascoy, Bryan Grounds, SeaHUG
Sounds good, what time?  1:00?  Please send a link for the meeting.

Bryan Grounds

unread,
Mar 31, 2021, 2:20:11 PM3/31/21
to SeaHUG
1PM pacific time sounds good to me.

Jitsi sounds good, too.

I imagine we'll need to send the meeting link on Saturday? Or can we set it up early?

https://en.m.wikipedia.org/wiki/Jitsi

Brian Gomes Bascoy

unread,
Mar 31, 2021, 2:46:48 PM3/31/21
to Bryan Grounds, SeaHUG
I believe we can choose a name now, say:

(1pm PST is good)

Bryan Grounds

unread,
Mar 31, 2021, 3:37:36 PM3/31/21
to SeaHUG
https://meet.jit.si/SeaHUG is perfect :)

Now I wonder if we can attract more interest.
So far, potential topics for discussion include:
* Brian Bascoy's Haskell stuff
* Michael Kerekes' Manalang updates?
* My PureScript dominion clone

Feel free to expand on the above.

Anyone else have a topic in mind?

Aaron Vargo

unread,
Apr 2, 2021, 9:50:45 PM4/2/21
to SeaHUG
I'll probably be there

Brian Gomes Bascoy

unread,
Apr 3, 2021, 12:55:42 PM4/3/21
to Aaron Vargo, SeaHUG
Great! See you all at 1pm then

Cheers

Michael Kerekes

unread,
Apr 3, 2021, 1:17:09 PM4/3/21
to Aaron Vargo, SeaHUG
I can say something about the state of the Mana compiler.  There are many things I could talk about.  You guys could AMA me.  I have settled on the, hopefully, final version of the type system.  I can say something about how pattern matching gadts works in Mana compared to GHC.

Brian Gomes Bascoy

unread,
Apr 3, 2021, 3:58:41 PM4/3/21
to Michael Kerekes, Aaron Vargo, SeaHUG
Sounds good. FYI I will be ~8 minute late, sorry

You received this message because you are subscribed to a topic in the Google Groups "SeaHUG" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/seattlehaskell/-bywinHg0eQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to seattlehaskel...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/seattlehaskell/CAFX_nGZqb_0JM9Wd%3DE13OxBqUrhJkEH0dCrz%2BdRK7A5AkB6pPg%40mail.gmail.com.

Michael Kerekes

unread,
Apr 3, 2021, 9:26:30 PM4/3/21
to Brian Gomes Bascoy, Aaron Vargo, SeaHUG
This just came to me.  Bryan, your best bet is probably using stack evaluation.  Information is passed to and returned from actions on a stack.  Here is an example implementation.  Your problem is harder since any action might interact with the user.  So you need to suspend evaluation between actions somehow.

data Action
  = Add
  | Literal Int
  | Print
  | Sequence [Action]

type SM = StateT [Int] IO

eval :: Action -> SM ()
eval (Literal  x ) = push x
eval (Add        ) = do { x <- pop; y <- pop; push (x + y) }
eval (Print      ) = pop >>= print
eval (Sequence as) = forM_ as eval

push :: Int -> SM ()
push v = modify (v :)

pop :: SM Int
pop = state \(v : vs) -> (v, vs)


Michael Kerekes

unread,
Apr 3, 2021, 11:23:56 PM4/3/21
to Brian Gomes Bascoy, Aaron Vargo, SeaHUG
You can solve the UI issue by keeping a list of pending actions and stepping one action at a time. Sequence then needs to push all of it's actions onto the pending list.

data Value
data Action = ASeq Action Action

type M = StateT (List Action, List Value) IO

step :: M ()
step = do
  popAction >>= \case
    None            -> return ()
    Some (ASeq a b) -> do
      pushAction b
      pushAction a
      step

    Some (a       ) -> do
      -- do other action
      return ()

popAction  :: M (Maybe Action)
pushAction :: Action -> M ()

Bryan Grounds

unread,
Apr 4, 2021, 8:06:24 PM4/4/21
to SeaHUG
Thanks for the tips, Michael.

I tried implementing a stand-alone Bind constructor for my Choice type.
I got it to compile, but it just evaluates the first Choice and drops everything else.

I think you're right about stack manipulation.
In the current implementation, each player already has a stack of choices.
Other Choice combinators like `And` push additional choices onto a player's stack, which then get processed in turn.
But each component Choice of `And` can be evaluated independently, whereas we have to pass information between the two component choices in a `Bind`.

Another detail that makes this challenging is that we actually have 2 Choice interpreters: one built into the game logic to decide how to modify game state, and another in the UI that decides how to present these choices, accept user input, and funnel that back into the game state. That's no problem for `And`, because the component Choices of `And` can be evaluated independently. We just push each of them on the stack and evaluate until the stack is empty.

So how do we pass information between the components of `Bind`?

Not sure, but I'm currently thinking I'll need something along these lines (code simplified to focus on the interesting bits).
I think it's in the spirit of what you suggested above.
What do you think?

data Choice
 = ...
 | DiscardAnyNumber
 | Bind { ma :: Choice, lambda :: Choice }
 | Lambda { a :: Maybe a, expression :: ChoiceExpression }
 | EvalAndForwardResult { choice :: Choice } -- not sure if I should actually have a special choice for saving the result of a previous choice, or if I should just always save the result and discard it unless it's needed

-- I'll need a constructor for each kind of lambda I want to be able to express (for serialization)
data ChoiceExpression
 = ...
 | DrawN -- an interpreter will take the DrawN constructor and an Int and construct a Choice.DrawN

cellar = Bind
 { ma: EvalAndForwardResult { choice: DiscardAnyNumber } }
 , lambda: Lambda { a: Nothing, expression: DrawN } -- the Nothing will be replaced with `Just a` after it's computed based on user input
 }

-- game logic interpreter
resolveChoice choice = case choice of
 ...
 Bind { ma, lambda } -> -- push ma and lambda onto the stack
 EvalAndForwardResult { choice } -> -- eval choice, then expect a lambda to be on the stack and insert the result into it
 Lambda { a, expression } -> -- by the time this is evaluated, a value should have been inserted for a, so we can construct a Choice from a and expression

Michael Kerekes

unread,
Apr 5, 2021, 12:37:52 AM4/5/21
to Bryan Grounds, SeaHUG
With a quick read, I can't tell if what you have will work.

One nice thing about the stack machine is serialization is very easy.  It's just a list of actions.

cellar = [ chooseDiscard, dup, discard, draw ] 

dup duplicates the top of the stack so it can be passed to two actions

SM is also easily extensible. superCellar draws twice as many cards as discarded.

superCellar = [ chooseDiscard, lit 2, mul, draw ]

Bryan Grounds

unread,
Apr 5, 2021, 3:20:44 AM4/5/21
to Michael Kerekes, SeaHUG
Ah, a stack machine. Like a calculator. I see what you mean now. Interesting. I'll have to give that a shot. Thanks!

Bryan Grounds

unread,
Apr 13, 2021, 3:59:58 AM4/13/21
to SeaHUG
Stack evaluation works!

I implemented a rough draft that adds a StackChoice constructor to support stack evaluation.
This commit shows that work, and the Cellar card implemented using this new mechanism.
The interesting bits are the card definition in src/Data/Cards.purs, and the interpreter defined in src/Data/GameState.purs (the new StackChoice case inside of the resolveChoice function).
https://gitlab.com/bagrounds/purescript-wip/-/commit/f3a8cc6700a93a8b55a38b9084e5c8e117e8ed8d
It still needs some polish, but the card works as expected.

Since this new strategy is more general than what I was doing before, I'll probably redefine all existing choices this way.

In addition to the added generality, this approach is more modular.
I like that it allows me to define Choices out of more fine-grained components.

A potential down-side: this simple stack evaluation strategy isn't strongly typed, so I introduce a lot more possibilities for runtime errors.
Considering that my long-term plan is to allow all cards to be user-defined, (thus not really compiled, but deserialized at run-time) maybe this isn't a big deal.
But who knows, maybe I'll have to take a look at https://kittenlang.org/ to figure out how to add type safety.

Thanks for the idea, Michael!

Bryan

Michael Kerekes

unread,
Apr 13, 2021, 6:41:28 PM4/13/21
to Bryan Grounds, SeaHUG
Glad it worked.  You can do type checking for a stack machine.  Each action has types for its input and outputs. 

add : (Int, Int) -> Int
literalInt : () -> Int

Type checking maintains a list of the types of the values that would be on the stack.  Type checking works like evaluation does, except that you are pushing and popping types instead of values.


Conal Elliott

unread,
Apr 13, 2021, 6:53:49 PM4/13/21
to Michael Kerekes, Bryan Grounds, SeaHUG
Another simple, typed formulation of stack machines dispenses with lists altogether and is described in Calculating compilers categorically (and the talk linked there).

Bryan Grounds

unread,
Apr 14, 2021, 1:02:42 PM4/14/21
to Conal Elliott, Michael Kerekes, SeaHUG
Thanks for the tips Michael, Conal!

Great talk, Conal. I really enjoy your examples on denotational design.

I was able to implement most of your paper/slides in PureScript. The language is so close to Haskell, most of it translated verbatim.


PureScript doesn't have GADTs, so I followed a recipe to translate GADTs into a "tagless final" encoding, using type classes.

Note: I believe I spotted small a typo in your paper/slides - towards the end (PDF page 9), you define a Monoidal instance for StackFun, but it should be StackProg.

If I understand correctly, in order to use this, my next step should be to extend Prim with all of the functionality I need to write my stack programs.

Conal Elliott

unread,
Apr 14, 2021, 2:54:41 PM4/14/21
to Bryan Grounds, Michael Kerekes, SeaHUG
Hi Bryan. I'm glad you enjoyed the paper & talk. Coincidentally, I'm reusing the essential idea now for hardware synthesis in Agda.

Thanks for passing along that typo!

If I understand correctly, in order to use this, my next step should be to extend Prim with all of the functionality I need to write my stack programs.

Exactly. Enjoy!    - Conal


Michael Kerekes

unread,
Apr 15, 2021, 12:25:01 PM4/15/21
to Conal Elliott, Bryan Grounds, SeaHUG
Very nice.  I started to write out something like StackProg in my previous e-mail, but I was indexing on lists of types, and it got complicated quickly, so I deleted all of it.  Pairs work much better.
Reply all
Reply to author
Forward
0 new messages