views:

210

answers:

3

In Monads for natural language semantics, Chung-Chieh Shan shows how monads can be used to give a nicely uniform restatement of the standard accounts of some different kinds of natural language phenomena (interrogatives, focus, intensionality, and quantification). He defines two composition operations, A_M and A'_M, that are useful for this purpose.

The first is simply ap. In the powerset monad ap is non-deterministic function application, which is useful for handling the semantics of interrogatives; in the reader monad it corresponds to the usual analysis of extensional composition; etc.

This makes sense. The secondary composition operation, however, has a type signature that just looks bizarre to me:

(<?>) :: (Monad m) => m (m a -> b) -> m a -> m b

(Shan calls it A'_M, but I'll call it <?> here.) The definition is what you'd expect from the types; it corresponds pretty closely to ap:

g <?> x = g >>= \h -> return $ h x

I think I can understand how this does what it's supposed to in the context of the paper (handle question-taking verbs for interrogatives, serve as intensional composition, etc.). What it does isn't terribly complicated, but it's a bit odd to see it play such a central role here, since it's not an idiom I've seen in Haskell before.

Nothing useful comes up on Hoogle for either m (m a -> b) -> m a -> m b or m (a -> b) -> a -> m b.

Does this look familiar to anyone from other contexts? Have you ever written this function?

+4  A: 

Just playing around in the ghci, I tried out the following:

> [length, sum, maximum, minimum, const 666] <?> [1, 2, 3]
[3, 6, 3, 1, 666]

> Nothing <?> Nothing
Nothing
> Just (maybe 0 (^2)) <?> Just 7
49
> Just (maybe 0 (^2)) <?> Nothing
0

> :m + Control.Monad.Instances

> (((+2) >>=) <?> 3) (^) -- (3+2)^3
125
> (((+2) .) <?> 3) (^4) -- (3^4)+2
83
> ((. (+2)) <?> 3) (^4) -- (3+2)^4
625

I think I have actually written the list specific version of this. Of all these examples, I find the list version the most enlightening toward the general case.

trinithis
+5  A: 

Part of the reason it looks strange may be the (m a -> b) part--that's actually a restriction from the most polymorphic type inferred for the given implementation, and taken out of context would be nonsensical for a monad. The most general type looks like this:

> :t (\g x -> g >>= \h -> return $ h x)
(\g x -> g >>= \h -> return $ h x) :: (Monad m) => m (t -> a) -> t -> m a

A more general version of this can be written without using monads at all:

a'_F :: (Functor f) => f (a -> b) -> a -> f b
a'_F g x = fmap ($ x) g

It doesn't seem to be relevant here, but a type like f a -> b does resemble the second argument to the cobind operation on a comonad:

(=>>) :: (Comonad w) => w a -> (w a -> b) -> w b
camccann
Ah, the functor version is very clear :D
trinithis
This is a generalization of flip (for (r->) functor).
sdcvvc
+1  A: 

This reminds me of the loeb function:

> loeb :: Functor a => a (a x -> x) -> a x
> loeb x = fmap (\a -> a (loeb x)) x

loeb ties knots. What that means is that if a is some kind of container, loeb makes a container from a container of rules saying how to make each element from the final result.

<?> is similar but instead of applying the rules to its own final result it applies the rules to another container, so it's no longer circular.