Проблема в том, что (insertm x y left)
- это Maybe (BinaryTree a b)
in:
| x < val = Just (Node val key (insertm x y left) right)
не BinaryTree a b
, поэтому вы не можете просто создать такой BinaryTree
с Maybe (BinaryTree a b)
как поддерево.
Однако вы можете «распаковать» значение и использовать его, например:
insertm :: (Ord a, Show a, Show b) => a -> b -> BinaryTree a b -> Maybe (BinaryTree a b)
insertm val key Leaf = Just (Node val key Leaf Leaf)
insertm x y (Node val key left right)
| x == val = Nothing
| x < val = case insertm x y left of
Just l -> Just (Node val key l right)
Nothing -> Nothing
| otherwise = case insertm x y right of
Just r -> Just (Node val key left r)
Nothing -> Nothing
Приведенный выше шаблон довольно популярен, мы можем использовать fmap :: Functor f => (a -> b) -> f a -> f b
здесь, чтобы отобразить x
в Just x
на Just (f x)
и карту Nothing
на Nothing
:
insertm :: (Ord a, Show a, Show b) => a -> b -> BinaryTree a b -> Maybe (BinaryTree a b)
insertm val key Leaf = Just (Node val key Leaf Leaf)
insertm x y (Node val key left right)
| x == val = Nothing
| x < val = fmap (flip (Node val key) right) (insertm x y left)
| otherwise = fmap (Node val key left) (insertm x y right)
или как @ JonPurdy говорит:
insertm :: (Ord a, Show a, Show b) => a -> b -> BinaryTree a b -> Maybe (BinaryTree a b)
insertm val key Leaf = Just (Node val key Leaf Leaf)
insertm x y (Node val key left right)
| x == val = Nothing
| x < val = Node val key <$> insertm x y left <*> pure right
| otherwise = Node val key left <$> insertm x y right
(<$>)
- это функция, которая эквивалентна fmap
, а (<*>) :: f (a -> b) -> f a -> f b
- это функция, которая принимает здесь Maybe (BinaryTree a b -> BinaryTree a b)
и применяет функцию f
, обернутый в Just
со значением x
, обернутым в правое Just
и возвращает Just (f x)
, если оба значения равны Just
с, если один из двух равен Nothing
(или оба) , тогда он вернет Nothing
.