Tree a
не монада, либо в целом, или для какой-либо конкретной a
, Tree
сама является монадой. Монада не является типом, это соответствие между любым типом и «монадической версией» этого типа. Например, Integer
является типом целых чисел, а Maybe Integer
является типом целых чисел в монаде Maybe
.
Следовательно, StringTree
, который является типом, не может быть монадой. Это не то же самое. Вы можете попытаться представить это как тип строк в монаде, но ваши функции stringTreeReturn
и т. Д. Не соответствуют типам их монадических корреспондентов. Посмотрите на тип >>=
в Maybe
монады:
Maybe a -> (a -> Maybe b) -> Maybe b
Второй аргумент является функцией от некоторых a
к любого типа в Maybe
монады (Maybe b
).stringTreeBind
имеет тип:
String -> (String -> StringTree) -> StringTree
Второй аргумент может быть только функцией от String
к монадической версии String
, а не к монадической версии любого типа.
Следовательно, вы не можете сделать все, что вы можете сделать, для значений в произвольном монадическом типе до значений StringTree
, поэтому его нельзя сделать экземпляром. Даже если бы вы каким-то образом восприняли его как монаду, все начнется неправильно, если общий монадический код ожидает, что он сможет использовать общие монадические операции способами, которые не имеют смысла для StringTree
.
В конце концов, если вы думаете о нем, как «как» монада, потому что это в контейнере, который может вести себя так же, как монадические контейнеры String
, проще всего сделать, это просто сделать общий контейнер любого типа (Tree a
). Если вам нужна вспомогательная функциональность, которая зависит от того, что она является деревом строк, вы можете записать этот код как действующий только по значениям Tree String
, и он будет успешно сосуществовать вместе с кодом, который работает в основном на Tree a
.
Что привело бы к 'fmap (const())? –
Вы можете даже сделать 'stringTreeFMap :: (String -> String) -> (StringTree -> StringTree)', но для того, чтобы действительно быть монадой в смысле теории категорий, вам нужно «join :: m (ma) -> ma ', который не подходит вообще. –
Просто из любопытства, почему вы не можете просто определить: 'type StringTree = Tree String'? –