Я иногда сталкивался с шаблоном в коде, который напоминает монаду, но
не поддерживает согласованный тип в >>=
.
Вот простейший пример, который я мог бы придумать:
(Сначала несколько булевых типов уровня:
data TyT = TyT
data TyF = TyF
class TyOr a b c | a b -> c
instance TyOr TyF TyF TyF
-- rest similarly
)
Теперь вот наш конструктор типа "монада":
data Marked p a = Marked a
deriving (Show)
Для данного p
, Marked p
является * -> *
, который очень похож на m
в
монады, но разные, как это происходит дальше, когда мы определяем "bind":
(>>%) :: (TyOr p q r) => Marked p a -> (a -> Marked q b) -> Marked r b
(Marked x) >>% f = Marked y where Marked y = f x
Что здесь отличает то, что результат >>%
имеет другой тип
конструктор, чем аргументы. Кроме того, это в основном монада.
Мы могли бы использовать его следующим образом:
a :: Marked TyF Int
a = Marked 5
f :: Int -> Marked TyT Int
f x = Marked (x + 1)
ghci> a >>% f
Marked 6
ghci> :t a >>% f
a >>% f :: Marked TyT Int
(Это было вдохновлено наблюдением outis, что Python с" не может быть monad, потому что он меняет тип, но я видел его другими способами (проще) тоже).