VEYA VEYA VEYA VEYA VEYA VEYA VEYA VEYA VEYA VEYA YOL AÇIĞI için mplus
ile eşlenen VEYA VEYA karar ağacı oluşturmak için bir EDSL oluşturmak için ücretsiz bir monad kullanmaya çalışıyorum. A AND (B OR C) AND (D OR E)
gibi bir şeyi tanımlamak istiyorum, ancak bunu dağıtımın (A AND B AND D) OR (A AND B AND E) OR (A AND C AND D) OR (A AND C AND E)
'a dönüştürmesini istemiyorum. Sonuç olarak, çözücünün ele almasını istediğim alternatiflerin sayısında kombinatoryal patlamaya neden olmadan AND/OR düğümlerini bir kısıtlayıcı çözücüde birleştirilmiş kısıtlamalara dönüştürmek istiyorum. Control.MonadPlus.Free
olarakControl.MonadPlus.Free dağıtımsız ücretsiz
, Plus ms >>= f
f
ms
her monadın altında Pure
yaprakların her tatbik edilmesine neden olur. Bu gereklidir, çünkü f
, değiştirdiği her bir Pure
yaprak için farklı bir değer verebilir.
Plus ms >> g
yılında,
g
yüzden
Plus
üzerinde dağıtmadan gereksiz görünüyor,
ms
yapraklarından herhangi etkilenen edilemez. ardından İşte
data Free f a = Pure a
| Free (f (Free f a))
| Then [Free f()] (Free f a)
| Plus [Free f a]
, yeni Then
yapıcı değeri biz görmezden monads dizisi tutar:
deneme yanılma yoluyla, ben yeni Then
kurucu ile Control.MonadPlus.Free
monad uzatmak olabilir bulundu Gerçek değeri veren son monad.
instance Functor f => Monad (Free f) where
return = Pure
Pure a >>= f = f a
Free fa >>= f = Free $ fmap (>>= f) fa
Then ms m >>= f = Then ms $ m >>= f
Plus ms >>= f = Plus $ map (>>= f) ms
Pure a >> mb = mb
Then ms ma >> mb = Then (ms ++ [ma >>= (const $ return())]) mb
ma >> mb = Then [] ma >> mb
>>
operatör "kapakları" Pure()
ile Pure a
değiştirerek varolan herhangi yaprakları, listeye şapkalı monad ekler ve yenisi ile değer monad yerine geçer: gibi yeni Monad
örneği görünüyor. ++
ile yeni monad eklenmesi verimsizliğinin farkındayım, amafmap
ile zincirinin sonuna yeni monosunu dikiş gibi (ve her şey devamları kullanarak yeniden yazılabilir) kadar kötü olduğunu düşünüyorum.
Bu, yapılması mantıklı bir şey gibi görünüyor mu? Bu, monad yasalarını ihlal ediyor mu (bu mesele mi?) Veya mevcut Control.Monad.Free
'u kullanmanın daha iyi bir yolu var mı?