Last active
July 21, 2026 07:22
-
-
Save arialdomartini/d06a0bb2e7b0d1f2997d3fbea8fbaecd to your computer and use it in GitHub Desktop.
cata.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| namespace Catamorphisms.RecursiveTypes; | |
| record Book(string Title, decimal Price); | |
| abstract record ChocolateType; | |
| sealed record Black : ChocolateType; | |
| sealed record Milk : ChocolateType; | |
| sealed record SeventyPercent : ChocolateType; | |
| record Chocolate(ChocolateType ChocolateType, decimal Price); | |
| abstract record WrappingPaperStyle; | |
| sealed record HappyBirthday : WrappingPaperStyle; | |
| sealed record HappyHolidays : WrappingPaperStyle; | |
| sealed record SolidColor : WrappingPaperStyle; | |
| abstract record Gift; | |
| sealed record BookGift(Book Book) : Gift; | |
| sealed record ChocolateGift(Chocolate Chocolate) : Gift; | |
| sealed record Wrapped(Gift Gift, WrappingPaperStyle WrappingPaperStyle) : Gift; | |
| sealed record Boxed(Gift Gift) : Gift; | |
| sealed record WithACard(Gift Gift, string Message) : Gift; | |
| static class Prices | |
| { | |
| const decimal WrappedPrice = 0.5m; | |
| const decimal BoxedPrice = 1m; | |
| const decimal WithACardPrice = 2m; | |
| } | |
| static TResult Cata<TResult>( | |
| Func<Book, TResult> fBook, | |
| Func<Chocolate, TResult> fChocolate, | |
| Func<TResult, WrappingPaperStyle, TResult> fWrapped, | |
| Func<TResult, TResult> fBoxed, | |
| Func<TResult, string, TResult> fWithACard, | |
| Gift gift) | |
| { | |
| // let recur = cata fBook fChocolate fWrapped fBoxed fWithACard | |
| TResult Recur(Gift g) => Cata(fBook, fChocolate, fWrapped, fBoxed, fWithACard, g); | |
| return gift switch | |
| { | |
| BookGift b => fBook(b.Book), | |
| ChocolateGift c => fChocolate(c.Chocolate), | |
| Wrapped w => fWrapped(Recur(w.Gift), w.WrappingPaperStyle), | |
| Boxed b => fBoxed(Recur(b.Gift)), | |
| WithACard w => fWithACard(Recur(w.Gift), w.Message), | |
| _ => throw new ArgumentOutOfRangeException(nameof(gift)) | |
| }; | |
| } | |
| static decimal TotalCost(Gift gift) => Gifts.Cata<decimal>( | |
| fBook: b => b.Price, | |
| fChocolate: c => c.Price, | |
| fWrapped: (inner, _) => inner + Prices.WrappedPrice, | |
| fBoxed: inner => inner + Prices.BoxedPrice, | |
| fWithACard: (inner, _) => inner + Prices.WithACardPrice, | |
| gift); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment