#StateMonadTransformer

2024-09-25

To my surprise, the idea I had last night is actually working just fine in #RustLang.

So, my #VisualNovel #SpareTimeProject is now probably going to use an #eDSL encoded as a #FreeMonad which is wrapped in a #StateMonadTransformer.

Now I just need to continue working on it. I haven't made much progress in the last 9 months...

Screenshot of the beginnings of an eDSL for a visual novel, implemented in Rust.

It currently only has 3 commands, which are changing the background, giving the player options, and presenting exposition.

The source code visible in the image is:
#[derive(Clone)]
pub enum Vn<'next, Next, TextureId>{
    Exposition{
        text : String,
        next : Next,
    },
    PlayerChoice{
        text : String,
        options : PlayerOptions<'next, Next>
    },
    SetBackground{
        background : TextureId,
        next : Next,
    }
}

impl<'a, A : 'a, TextureId> Functor<'a, A> for Vn<'a,A, TextureId>{
    type Target<T> = Vn<'a, T, TextureId>;

    fn fmap<B, F>(self, f: F) -> Self::Target<B>
    where
        F: Fn(A) -> B + 'a {
        match self {
            Vn::Exposition { text, next } => Vn::Exposition { text: text, next: f(next) },
            Vn::PlayerChoice { text, options } => Vn::PlayerChoice { text, options : options.fmap(f) },
            Vn::SetBackground { background, next } => Vn::SetBackground { background: background, next: f(next) },
        }
    }
}

free!(<'a>, pub FreeVnRaw<'a, A, TextureId>, Vn<'a, FreeVnRaw<'a, A, TextureId>, TextureId>);

pub type FreeVn<'a, A, TextureId, GameState> = StateT<'a, GameState, FreeVnRaw<'a, (A, GameState), TextureId>>;

pub fn exposition<'a, TextureId : Clone + 'a, GameState : Clone +'a>(text : String) -> FreeVn<'a, (), TextureId, GameState>{
    FreeVn::lift(FreeVnRaw::lift_f(Vn::Exposition { text, next: () }))
}

Client Info

Server: https://mastodon.social
Version: 2025.04
Repository: https://github.com/cyevgeniy/lmst