Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
関数型LT大会発表資料
module Main where
import Game.NovelMonad
import Game.NovelMonad.SimpleInterpreter
import Story
main :: IO ()
main = simpleInterpret defaultConfig novelMain
novelMain :: Novel ()
novelMain = do
talk Narrator ""
talk Narrator "Operationalモナドで紡ぐ物語"
talk Narrator ""
talk Narrator " ちゅーん(@its_out_of_tune)"
talk Narrator " Haskell lover"
trunOverThePage
shortStory
aboutNovelMonad
-----
aboutNovelMonad :: Novel ()
aboutNovelMonad = do
talk Narrator ""
talk Narrator "はいw"
talk Narrator ""
talk Narrator "ショートストーリー圏論マン"
talk Narrator "楽しんで頂けたでだろうか"
talk Narrator ""
trunOverThePage
talk Narrator "RPGやノベルゲームのシナリオは、"
talk Narrator "専用のDSLを用いて記述し"
talk Narrator "それをパース/インタプリタ実行するのが"
talk Narrator "もっとも良く用いられる手法だと思われる。"
trunOverThePage
talk Narrator "では、今回の掛け合いの場合は、"
talk Narrator "どのようになっているか見てみよう。"
talk Narrator ""
talk Narrator "(実際に見てもらう)"
talk Narrator ""
trunOverThePage
talk Narrator "しかしそれには、以下のような問題がある"
talk Narrator ""
talk Narrator " -> 学習コストが高い"
talk Narrator " -> 言語としての完成度があまり高くない"
talk Narrator " (出来る事が少ない)"
talk Narrator " -> 実装コストがめちゃ高い"
trunOverThePage
talk Narrator "モナドとは、一般化した手続きである。"
talk Narrator "RPGやノベルゲームのシナリオは手続きである"
talk Narrator ""
talk Narrator "先ほどお見せしたように、"
talk Narrator "専用のモナドを実装する事で"
talk Narrator "ゲームのシナリオを手続き的に、"
talk Narrator "良い感じに書けるようになる"
trunOverThePage
talk Narrator "IOアクションを追加するだけではダメなのか?"
talk Narrator ""
talk Narrator "### IOの分離 ###"
talk Narrator " -> ゲームシナリオとは無関係なIOアクションを分離"
talk Narrator " -> 型を分離する事による問題の切り分け"
talk Narrator ""
talk Narrator "### シナリオとゲーム本体の分離 ###"
talk Narrator " -> 上手く実装すればゲーム本体とシナリオを分離可能"
talk Narrator " -> GUIが実装されてなくてもCUI上で簡単にシミュレート"
trunOverThePage
talk Narrator "専用DSLで問題となっていた事は大体解消される"
talk Narrator ""
talk Narrator " -> 学習コスト"
talk Narrator " いくつかのIOアクションを覚えれば良い"
talk Narrator " Haskellの制御構文が使える"
talk Narrator " -> 言語としての完成度"
talk Narrator " Haskell上でHaskellそのまま書けるんですよ?"
talk Narrator " なので当然、モナディック関数使いたい放題!!"
trunOverThePage
talk Narrator "皆さんの声"
talk Narrator ""
talk Narrator "「でもお高いんでしょう?」"
talk Narrator "(開発コストが)"
talk Narrator ""
trunOverThePage
talk Narrator ""
talk Narrator "そこでOperationalモナドですよ!!!"
talk Narrator ""
talk Narrator ""
talk Narrator "(ここで会場がどよめく)"
talk Narrator ""
trunOverThePage
talk Narrator "NovelMonadの実装がどのようになっているか、"
talk Narrator "実際に見てみよう。"
talk Narrator ""
talk Narrator "(実際に見てもらう)"
talk Narrator ""
trunOverThePage
talk Narrator "ご覧頂いたように、とても簡単に、"
talk Narrator "新たなモナドを作ることができる"
talk Narrator ""
talk Narrator "何故こんな事ができるのだろうか?"
trunOverThePage
talk Narrator "Operationalの仕組み"
talk Narrator ""
talk Narrator " -> CoYoneda"
talk Narrator " 任意の型をFunctorにする"
talk Narrator " 圏論から生まれたヤバイ仕組み"
talk Narrator " -> Free"
talk Narrator " 任意のFunctorをMonadにする"
talk Narrator " 圏論から生まれたヤバイ仕組み"
talk Narrator ""
talk Narrator "この二つが組み合わされば任意の型がMonadになるのは、"
talk Narrator "自明である。な、なんだっt(ry"
trunOverThePage
talk Narrator "本日のまとめ"
talk Narrator ""
talk Narrator " 圏論ヤバイ、でも..."
talk Narrator " 圏論の恩恵を受けたHaskellはめっちゃ便利"
talk Narrator ""
talk Narrator " ゲームに限らず、ちょっとしたDSLが欲しくなったら"
talk Narrator " HaskellでOperationalモナドを使おう!"
talk Narrator ""
trunOverThePage
talk Narrator ""
talk Narrator " ありがとうございました! "
talk Narrator ""
trunOverThePage
module Story where
import Game.NovelMonad
shortStory :: Novel ()
shortStory = do
(boy, girl) <- createActors
trunOverThePage
talk boy "今日は良い天気だなぁ!昨日までの雨が嘘みたいだ!"
talk Narrator "日の光がさんさんと降り注ぐ昼下がり。"
talk Narrator $ actorName boy ++ "はパソコンのキーを叩きながら言った。"
talk girl "本当ね。"
talk Narrator $ actorName girl ++ "がエクセル方眼紙の資料を纏めながら答える。"
trunOverThePage
talk Narrator "リリース日まであと21時間、さまざまな困難を乗り越え"
talk Narrator "プロジェクトは収束を迎えようとしていた。"
talk Narrator ""
talk boy "さあ、もうお昼だね、一緒にご飯でも食べに行かないかい?"
talk girl "素敵! わたし、この近くに素敵なパスタ屋さんを知っているの。"
talk Narrator "と、その時である..."
trunOverThePage
talk siyouhenko "ふふふふ!そうはさせないわよ!!"
talk Narrator "バーン!大きな音を立て扉が開け放たれ、"
talk Narrator "怪しげな女が部屋に飛び込んできた!"
trunOverThePage
talk boy "誰だお前は!"
talk siyouhenko $ "私の名は" ++ actorName siyouhenko
talk siyouhenko "お前たちのプロジェクトはもう終わりだ!"
talk Narrator "なんという事だろう。リリース間近の仕様変更、"
talk Narrator "未だかつて、この脅威から逃げられたエンジニアは"
talk Narrator "一人足りとも存在しないのだ。"
trunOverThePage
talk boy "おお!どうしたら良いんだ!"
talk girl $ "助けて!" ++ actorName kenronman ++ ""
talk Narrator "その時、まばゆい光とともに"
talk Narrator "屈強な男がプロジェクトルームに飛び込んできた!"
trunOverThePage
talk kenronman "待たせてすまない、後はこの俺に任せてくれ!"
talk siyouhenko $ "来たわね" ++ actorName kenronman ++ "、でも無駄よ!"
talk siyouhenko "今日の私は今までとは一味違うわ!"
talk siyouhenko "実現には、大半のテーブル定義を変更する必要があるの!"
trunOverThePage
special --必殺技発動
talk siyouhenko "まっ・・・まいったー!!"
talk Narrator $ "怪人" ++ actorName siyouhenko ++ "は、ほうほうのていで退散した"
talk Narrator ""
talk boy $ "すごいぞ!" ++ actorName kenronman ++ ""
talk girl $ "どうもありがとう!" ++ actorName kenronman ++ ""
talk Narrator $ "こうして今日もまた、" ++ actorName kenronman ++ "の手によって、"
talk Narrator $ "プロジェクトがひとつ、救われたのであった。"
trunOverThePage
talk Narrator ""
talk Narrator " 〜 Fin ~ "
talk Narrator ""
trunOverThePage
---
special :: Novel ()
special = do
s <- selectChoices $ do
talk kenronman "ぐぬぬ。。。"
talk kenronman "ならば、これでも喰らえ!"
case s of
MonadPanchi -> do
talk kenronman "自己関手の圏におけるモノイド対象!"
talk kenronman "必殺!モナドパーンチ!"
SoutuiBeam -> do
talk kenronman "いでよ!対となる圏からの射!"
talk kenronman "必殺!双対ビーム"
NaturalSmash -> do
talk kenronman "これぞ圏論の真髄、はじまりの力、喰らえ!"
talk kenronman "自然変換スマッシュ!"
data Specials = MonadPanchi | SoutuiBeam | NaturalSmash deriving (Enum, Bounded)
instance Choices Specials where
showItem MonadPanchi = "モナドパンチ"
showItem SoutuiBeam = "双対ビーム"
showItem NaturalSmash = "自然変換スマッシュ"
---
createActors :: Novel (Actor, Actor)
createActors = do
boyName <- getStrLn (talk Narrator "男の子の名前を入力してね")
boy <- return $ Actor
{ actorName = boyName
, actorSex = Boy
}
girlName <- getStrLn (talk Narrator "女の子の名前を入力してね")
girl <- return $ Actor
{ actorName = girlName
, actorSex = Girl
}
return (boy, girl)
kenronman :: Actor
kenronman = Actor
{ actorName = "圏論マン"
, actorSex = Boy
}
siyouhenko :: Actor
siyouhenko = Actor
{ actorName = "仕様変更"
, actorSex = Girl
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment