Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Implement Monad instances for Either, Maybe and List #37
Richard, I'm stuck on this one. I defined open type classes to represent monadic functions:
type family (:>>=) (a :: k1) (b :: TyFun k2 k1 -> *) :: k1 type family (:>>) (a :: k1) (b :: k1) :: k1 type family Return (a :: k1) :: k2 $(genDefunSymbols [ ''(:>>=), ''(:>>), ''Return ])
Then I define instances. For example
$(promoteOnly [d| maybeReturn :: a -> Maybe a maybeReturn a = Just a maybeBind :: Maybe a -> (a -> Maybe a) -> Maybe a maybeBind (Just x) k = k x maybeBind Nothing _ = Nothing maybeBind' :: Maybe a -> Maybe a -> Maybe a maybeBind' (Just _) k = k maybeBind' Nothing _ = Nothing |]) type instance Return a = MaybeReturn a type instance a :>>= b = MaybeBind a b type instance a :>> b = MaybeBind' a b
Now here's a test:
$(promote [d| data Foo = A | B | C | D fooM1 :: Maybe Foo fooM1 = return A fooM2 :: Maybe Foo fooM2 = fooM1 >>= return |]) fooM1a :: Proxy FooM1 fooM1a = Proxy fooM1b :: Proxy (Just A) fooM1b = fooM1a fooM2a :: Proxy FooM2 fooM2a = Proxy fooM2b :: Proxy (Just A) fooM2b = fooM2a
It looks that application of
I was afraid something like this might happen.
First off, it looks like some of the declared types are slightly wrong. Here is I would write these definitions:
But, that’s not what’s broken. What’s broken (and can’t obviously be fixed) is the type of (:>>=), even as I’ve given it. That type makes no connection between
The solution, in this case, is to say this:
Now, GHC knows what to do and can proceed.
How to solve in the general case? I haven’t the foggiest idea. If ScopedTypeVariables actually worked sanely (see comments in Single.Monad.bindTyVars for this explanation), I think this would be fixable. As it stands, I’m not sure what the best solution is. Let me ponder a while and get back to you.
On Apr 25, 2014, at 4:23 AM, Jan Stolarek firstname.lastname@example.org wrote:
Well, I've pondered, and I'm stuck.
There seem to be two ways of fixing a problem like this, and I'm convinced neither of them work.
Way 1: Fix the type family / type instances so that GHC can do the right thing at use sites. First off, this fix must be in the type family, not instances, because GHC hasn't selected an instance by the time it must do something differently than its current behavior. And, GHC doesn't have kind families nor higher-sorted kind variables, so there's not much we can do in the family definition. If only a type family could have functional dependencies, we could get somewhere, but alas, no. (Sidenote: of course, a type family can be declared within a class with functional dependencies, but GHC doesn't apply the fundeps when examining the type family.)
Way 2: Beef up our promotion algorithm to give GHC enough hints to get this right. The problem is that this amounts to type inference, which is a Terrible Idea. The way we would have to do this is to poke around looking for, say, some function that returns a Maybe, realize that we're in the Maybe monad, and then mechanically replace
What next? We decide that (a) this is too important to be left out and then decide on some fragile heuristics in order to specialize the monadic combinators during promotion or (b) describe this as a limitation of our approach and an incentive to get GHC to fix its higher-sorted kind variables / functional dependencies in type families / lack of kind families.
(Of course, I'm working on implementing higher-sorted kind variables and kind families, among other goodies, but that's a separate story.)
What do you think?
Ah, yes. I noticed that later but it also didn't work.
+1 on this one. So we need to say that we don't really support do-notation and list comprehensions, although if user annotates every monadic computation with types then all should work, right?
Haha: "kinds of ty_foo and ty_bar match that of the outer context". Wasn't this supposed to be "surrounding scope" :-) Anyway, for me this comment is a bit out of context (no pun intended) but at least I know the source of all this let-defined