When I define >> function (with RebindableSyntax extension) and use it directly (mempty >> 1 >> 2 >> 3) everything works as expected, but when I use do block I get following error:
Couldn't match expected type ‘Integer’
with actual type ‘Aggregator Integer’
In a stmt of a 'do' block: 1
In the expression:
do mempty
1
2
3
In an equation for ‘notWorking’:
notWorking
= do mempty
1
2
3
Whole code:
{-# LANGUAGE RebindableSyntax #-}
module RebindableSyntaxStuff where
import Prelude hiding ((>>), (>>=), return)
newtype Aggregator a = Aggregator [a]
deriving(Show)
instance Semigroup (Aggregator a) where
(Aggregator xs) <> (Aggregator ys) = Aggregator (xs++ys)
instance Monoid (Aggregator a) where
mempty = Aggregator []
pack :: a -> Aggregator a
pack x = Aggregator [x]
working :: Aggregator Integer
working = mempty >> 1 >> 2 >> 3 --Returns Aggregator [1,2,3]
notWorking :: Aggregator Integer
notWorking = do
mempty
1
2
3
(>>) :: Aggregator Integer -> Integer -> Aggregator Integer
(>>) a b = (<>) a (pack b)
As I understand do will add >> on every new line, so it should work.
Where did I make a mistake?
Solution
The way Haskell desugars the do notation is right associative
I changed (>>) function to be infixr and also order of arguments. Code below:
working :: Aggregator Integer
working = 1 >> 2 >> 3 >> mempty
notWorking :: Aggregator Integer
notWorking = do -- Now works
1
2
3
mempty
infixr 0 >>
(>>) :: Integer -> Aggregator Integer -> Aggregator Integer
(>>) a = (<>) (pack a)