Skip to content

Instantly share code, notes, and snippets.

@kawasima
Created March 26, 2024 12:56
Show Gist options
  • Save kawasima/1d0aa2d66842f4895f996f2540faf42c to your computer and use it in GitHub Desktop.
Save kawasima/1d0aa2d66842f4895f996f2540faf42c to your computer and use it in GitHub Desktop.
7並べのモデル Domain Modeling Made Functional風味
import z from "zod";
const Suit = z.enum(["Spade", "Heart", "Diamond", "Club"]);
const Rank = z.enum(["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]);
const Card = z.object({
suit: Suit,
rank: Rank,
});
type Card = z.infer<typeof Card>;
// 手札
const Hand = z.array(Card);
type Hand = z.infer<typeof Hand>;
// 場
const Field = z.array(z.object({
suit: Suit,
rank: Rank,
card: Card.optional(),
}));
type Field = z.infer<typeof Field>;
const Player = z.object({
name: z.string(),
hand: Hand,
});
const SevensGame = z.object({
field: Field,
players: z.array(Player),
});
// 場に出すカードを選択する
type choicePlaceCard = (hand: Hand) => [Card, Hand];
// 選択したカードを場に出す
type placeCard = (field: Field, card: Card) => Field;
// ----------------------------------------
// 型で保護するならば…の場合
// 選択したものしか場に出せないので、PickupCard型を導入する。
// が、場に出てしまえば、Card型であることにはは変わりがない。
//
// すなわち、業務の振る舞いにおいて、異なる扱いをする必要があるところだけ型を作って
// 保護するのがDomain Modeling Made Functional流である。
//
// が、このケースではchoicePlaceCardとplaceCardは合成するのみしか使い道がない気がする
// ので、PickupCard型を導入する必要がないかも。
const PickupCard = Card.brand("PickupCard");
type PickupCard = z.infer<typeof PickupCard>;
type choicePlaceCard = (hand: Hand) => [PickupCard, Hand];
type placeCard = (field: Field, card: PickupCard) => Field;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment