モノイドで再帰的に酔う
免責事項:私はmixologistではありません.これはプロのカクテルのアドバイスではありません!
サムHorvathハントブログ.これはFPモデリングの本当にクールな例です.(Lennart Kolmodinはかつてタンゴのダンスステップがモノイドであると書きました.)
まず最初に、私はカクテルレシピが成分の上の自由な通勤モノであると仮定することによって私の無知を証明します: 成分を加える順序は問題ではない. あなたが一緒に2つのカクテルを加えるならば、あなたはもう一つのカクテルを得ます. アイデンティティカクテルは、それの成分がない空のカクテルです. 第二に、私は再帰的なカクテルのレシピでanteをアップしたい.
それは、DIKU(コペンハーゲン大学)のコンピュータサイエンス学生レビューのスケッチから来ます:Superdrinks (2002)クレジットは、Uffeクリステンセン、uffe friis lichtenberg、ジョナスUSsing、Niels H . Christensen、Torben .mogensen、jΦrgenエルガラードセンは、どちらかを書いたか、スケッチを制定しました.
スーパードリンクは以下からなる 1パートジン. レモン2パーツ. 3パーツスーパードリンク. 今、スケッチによると、この飲み物を具体化する多くの悪い方法がありますそのような1つは近似を通してあります:1つのパートGin、2つの部分レモンと3つの部分が何であっても、スーパードリンクのあなたの現在の最高の近似です.このプロセスを十分に繰り返すと、徐々に細かいスーパードリンクがあります.
再帰的に
少し実験する.
schwiftyを得る時間です.
ジントニックとスーパードリンクを作るには以下の成分が足ります.
デモンストレーション
サムHorvathハントブログ.これはFPモデリングの本当にクールな例です.(Lennart Kolmodinはかつてタンゴのダンスステップがモノイドであると書きました.)
まず最初に、私はカクテルレシピが成分の上の自由な通勤モノであると仮定することによって私の無知を証明します:
それは、DIKU(コペンハーゲン大学)のコンピュータサイエンス学生レビューのスケッチから来ます:Superdrinks (2002)クレジットは、Uffeクリステンセン、uffe friis lichtenberg、ジョナスUSsing、Niels H . Christensen、Torben .mogensen、jΦrgenエルガラードセンは、どちらかを書いたか、スケッチを制定しました.
スーパードリンクは以下からなる
再帰的に
superdrinks(n) = 1 × gin
+ 2 × lemon
+ 3 × superdrinks (n-1)
例えばsuperdrinks(0)
, それは水かもしれない.それはジンかもしれない!少し実験する.
superdrinks(1) = 1 × gin + 2 × lemon + 3 × superdrinks(0)
superdrinks(2) = 1 × gin + 2 × lemon + 3 × superdrinks(1)
= 1 × gin
+ 2 × lemon
+ 3 × (1 × gin + 2 × lemon + 3 × superdrinks(0))
= 4 × gin + 8 × lemon + 9 × superdrinks(0)
各成分の部分の数の関係はclosed form 排除superdrinks(n) = (3ⁿ - 1)/2 × gin
+ (3ⁿ - 1) × lemon
+ 3ⁿ × superdrinks(0)
(3×3×・・・n個の出現が3であることを認識して閉じた形を見つけることができますⁿ, スーパードリンク(0)より1つのより少ないレモンが常にあります、そして、常にそのジンの量の半分がそれであるということ;または、あなたはそれらを解決することができますrecurrence relation ; または、関数を使用して3つの番号のシリーズを展開することができます.> let superdrinks (gin, lemon, super) = (1 + 3*gin, 2 + 3*lemon, 3*super)
> unzip3 $ take 6 $ iterate superdrinks (0,0,1)
([0,1,4,13,40,121],[0,2,8,26,80,242],[1,3,9,27,81,243])
and look them up .)schwiftyを得る時間です.
ジントニックとスーパードリンクを作るには以下の成分が足ります.
data Ingredient = Gin | Tonic | Lemon
deriving (Eq, Ord, Show)
カクテルは、成分とその多様性の任意のセットです:newtype Cocktail = Cocktail (Map Ingredient Natural)
deriving (Eq, Ord, Show)
emptyCocktail :: Cocktail
emptyCocktail = Cocktail Map.empty
便宜上parts :: Natural -> Ingredient -> Cocktail
parts n ingredient =
Cocktail (Map.singleton ingredient n)
combine :: Cocktail -> Cocktail -> Cocktail
combine (Cocktail c1) (Cocktail c2) =
Cocktail (Map.unionWith (+) c1 c2)
このモデリングの結果は以下の通りです.> let gintonic = combine (1 `parts` Gin) (2 `parts` Tonic)
> gintonic == combine gintonic gintonic
False
これらはカクテルレシピですので、レシピが結局「2部ジン、4部トニック」または「0パートジン」と言わないように、各成分の量を正規化したいです.normalize :: Cocktail -> Cocktail
normalize (Cocktail ingredients) =
Cocktail . normalize' $ ingredients
where
scale = foldr1 gcd (Map.elems ingredients)
normalize' = Map.map (`div` scale) . Map.filter (/= 0)
(注意してくださいfoldr1
is partial , Haskellの非厳密な意味では、ingredients
内で使用されるので空ですMap.map
0回デモンストレーション
normalize
:> normalize emptyCocktail
Cocktail (fromList [])
> normalize (0 `parts` Gin)
Cocktail (fromList [])
> normalize $ combine (2 `parts` Gin) (4 `parts` Tonic)
Cocktail (fromList [(Gin,1),(Tonic,2)])
それは特殊化する誘惑されるEq Cocktail
使用するインスタンスnormalize
それでc == combine c c
すべてのためにc
. しかし、あなたが構造的平等のために比較する必要があるならば、あなたがそうすることができないので、私はそれをするのが好きでありません.> let (=~) = (==) `on` normalize
> (1 `parts` Gin) =~ (2 `parts` Gin)
True
また、正規化を追加することも魅力的でしょうcombine
つのカクテルの組み合わせが正規化カクテルです.しかし、このブログ記事はモノイドカクテルについてですのでcombine
構成演算子にとって最良の候補は、そのような選択は実際に連想性の法則を壊すことです.> let norm_combine c1 c2 = normalize (combine c1 c2)
> gin1 `norm_combine` (gin1 `norm_combine` tonic1)
Cocktail (fromList [(Gin,2),(Tonic,1)])
> (gin1 `norm_combine` gin1) `norm_combine` tonic1
Cocktail (fromList [(Gin,1),(Tonic,1)])
だから私はカクテルのレシピを正規化の概念が好きですが、それはSemigroup Cocktail
インスタンスは、おそらくより単純な例を残して、悪い考えであるでしょうinstance Semigroup Cocktail where
(<>) = combine
instance Monoid Cocktail where
mempty = emptyCocktail
スーパードリンクは、次のように表現できます.superdrinks :: Natural -> Cocktail -> Cocktail
superdrinks n base = mconcat
[ ((3^n - 1) `div` 2) `parts` Gin
, (3^n - 1) `parts` Lemon
, (3^n) `rounds` base
]
rounds :: Natural -> Cocktail -> Cocktail
rounds n = mconcat . genericReplicate n
最良の近似がベースを使用しているかどうかmempty
または、レビュースケッチが示唆するように.n `parts` Gin
, 非常に主観的です.第0近似として純粋ジンを用いたスーパードリンクの第5近似> normalize $ superdrinks 5 (1 `parts` Gin)
Cocktail (fromList [(Gin,182),(Lemon,121)])
乾杯!Reference
この問題について(モノイドで再帰的に酔う), 我々は、より多くの情報をここで見つけました https://dev.to/sshine/getting-recursively-drunk-with-monoids-2jekテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol