Gabriella439 / Haskell-MMorph-Library

Monad morphisms
BSD 3-Clause "New" or "Revised" License
47 stars 26 forks source link

Add mtrans to convert a monad to its transformation of Identity #41

Closed code5hot closed 3 years ago

code5hot commented 5 years ago

Hi,

Please would you take a look at this addition of 'mtrans' which just converts a monad to its equivalent transformer on Identity.

I don't really know if this is a very good idea so I'd appreciate your feedback. It makes it a lot easier to mix monads with monad transformer stacks and makes a shallower learning curve if one looks at the source code.

With this change we can now, for example, go from a maybe to a maybeT with a simple application of mtrans and we can followup up with a hoist from identity if we want to:

hoist generalize . mtrans

Gabriella439 commented 5 years ago

@code5hot: The first issue I can think of is that there is not a 1-to-1 mapping between the source and target monads. For example, ExceptT Identity can be converted to Either and Except. This can lead to type inference issues.

The second issue is that I can't think of examples where one would want to write code that is generic over MTrans.

However, I still think this would be useful if instead of a type class we took all of the non-id instances and translated them to named monomorphic functions.

code5hot commented 5 years ago

Ah the idea is not to go from a transformer to a monad but from a monad to a transformer. Now while it's true that there could be more than one transformer which subsumed the monad this can always be resolved with the type system.

All we need mtrans for is to give us any transformer stack with the same behaviours as the monad, combined with type annotations or unification we will be able to say: "give me a transformer stack for this monad" so you can start to use the other facilities of transformer stack with type unification and annotations to disambiguate.

We would say the same thing with a comment so it's a real concept for program description and construction and so then it must be able to be a function from one program to another.

On Tue, 5 Mar 2019, 03:11 Gabriel Gonzalez, notifications@github.com wrote:

@code5hot https://github.com/code5hot: The first issue I can think of is that there is not a 1-to-1 mapping between the source and target monads. For example, ExceptT Identity can be converted to Either and Except. This can lead to type inference issues.

The second issue is that I can't think of examples where one would want to write code that is generic over MTrans.

However, I still think this would be useful if instead of a type class we took all of the non-id instances and translated them to named monomorphic functions.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Gabriel439/Haskell-MMorph-Library/pull/41#issuecomment-469519037, or mute the thread https://github.com/notifications/unsubscribe-auth/AfPM5VkDbIzcM9QgwQb-ihtoR5izlAskks5vTeBIgaJpZM4bbWOB .

code5hot commented 5 years ago

I put together a brief example showing how it can be handy.

Now, it might not be something to aim to use, but whenever one needs to follow the straightforward pattern of "take a monad and use its transformer" we can avoid explaining our intention in comments by writing it directly in the code with mtrans so readers of any breadth of familiarity of monad transformers can understand the intention.

Below I demo Maybe, but it works for Either too (although you have to use a Monoid for the Left type) and it will work with a valid ListT such as that in other packages. I'm not sure if it will work with the one in this package which isn't a valid monad transformer.

λ> let a x = do x' <- hoist generalize $ mtrans x λ| lift $ putStrLn $ show x' λ| x'' <- ((x'-1) <$ do guard $ x' > 0) λ| lift $ putStrLn $ show x'' λ| λ> :t a a :: (MFunctor t, MTrans t m, MonadTrans t, Alternative (t IO), Show a, Ord a, Num a, Monad (t IO)) => m a -> t IO () λ> runMaybeT $ a (Just 2) 2 1 Just () λ> runMaybeT $ a (Just 1) 1 0 Just () λ> runMaybeT $ a (Just 0) 0 Nothing λ> runMaybeT $ a (Nothing) Nothing

On Tue, 5 Mar 2019 at 12:28, Tristan Wibberley tristan.wibberley@gmail.com wrote:

Ah the idea is not to go from a transformer to a monad but from a monad to a transformer. Now while it's true that there could be more than one transformer which subsumed the monad this can always be resolved with the type system.

All we need mtrans for is to give us any transformer stack with the same behaviours as the monad, combined with type annotations or unification we will be able to say: "give me a transformer stack for this monad" so you can start to use the other facilities of transformer stack with type unification and annotations to disambiguate.

We would say the same thing with a comment so it's a real concept for program description and construction and so then it must be able to be a function from one program to another.

On Tue, 5 Mar 2019, 03:11 Gabriel Gonzalez, notifications@github.com wrote:

@code5hot https://github.com/code5hot: The first issue I can think of is that there is not a 1-to-1 mapping between the source and target monads. For example, ExceptT Identity can be converted to Either and Except. This can lead to type inference issues.

The second issue is that I can't think of examples where one would want to write code that is generic over MTrans.

However, I still think this would be useful if instead of a type class we took all of the non-id instances and translated them to named monomorphic functions.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Gabriel439/Haskell-MMorph-Library/pull/41#issuecomment-469519037, or mute the thread https://github.com/notifications/unsubscribe-auth/AfPM5VkDbIzcM9QgwQb-ihtoR5izlAskks5vTeBIgaJpZM4bbWOB .

Gabriella439 commented 5 years ago

@code5hot: Alright, we can include this. If the conversion is in the other direction (from monad to transformer) then I can see how type inference is more likely to succeed

code5hot commented 5 years ago

@code5hot: Alright, we can include this. If the conversion is in the other direction (from monad to transformer) then I can see how type inference is more likely to succeed

In fact, the type inference both ways should be fine because our stack is always on Identity so it's an unambiguous class of typeclass instances ... I think ...

Gabriella439 commented 3 years ago

Closing as this pull request has gotten a bit old, but feel free to reopen again if you want to revisit this