在Monads for natural language semantics中,Chung-Chieh Shan展示了monad如何用于对一些不同类型的自然语言现象(疑问,焦点,内涵和量化)的标准叙述进行非常统一的重述。他定义了两个合成操作,A_M
和A'_M
,这些操作对此有用。
第一个只是ap
。在powerset中,monad ap
是非确定性函数应用程序,它对于处理疑问句的语义很有用;在读者monad中,它对应于拉伸成分的通常分析;等
这是有道理的。然而,二次合成操作的类型签名对我来说很奇怪:
(<?>) :: (Monad m) => m (m a -> b) -> m a -> m b
(Shan称之为A'_M
,但我在这里称之为<?>
。)定义是您对类型的期望;它与ap
非常接近:
g <?> x = g >>= \h -> return $ h x
我想我可以理解这是如何做到它在本文的背景下应该做的事情(处理疑问句的问题动词,作为内容构成等)。它的作用并不是非常复杂,但看到它在这里发挥如此重要的作用有点奇怪,因为它不是我以前在Haskell中看到的成语。
对于m (m a -> b) -> m a -> m b
或m (a -> b) -> a -> m b
这对其他任何人来说都很熟悉吗?你有没有写过这个函数?
答案 0 :(得分:6)
它看起来很奇怪的部分原因可能是(m a -> b)
部分 - 这实际上是对给定实现推断的最多态类型的限制,并且脱离上下文对于monad来说是荒谬的。最常见的类型如下:
> :t (\g x -> g >>= \h -> return $ h x)
(\g x -> g >>= \h -> return $ h x) :: (Monad m) => m (t -> a) -> t -> m a
可以在不使用monad的情况下编写更通用的版本:
a'_F :: (Functor f) => f (a -> b) -> a -> f b
a'_F g x = fmap ($ x) g
这里似乎没有相关性,但像f a -> b
这样的类型确实类似于comonad上cobind操作的第二个参数:
(=>>) :: (Comonad w) => w a -> (w a -> b) -> w b
答案 1 :(得分:4)
只是在ghci玩,我尝试了以下内容:
> [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
我想我实际上已经编写了这个列表的特定版本。在所有这些例子中,我发现列表版本对于一般情况最具启发性。
答案 2 :(得分:1)
这让我想起了loeb
function:
> loeb :: Functor a => a (a x -> x) -> a x
> loeb x = fmap (\a -> a (loeb x)) x
loeb
打结。这意味着如果a
是某种容器,loeb
从容器规则中创建一个容器,说明如何从最终结果中生成每个元素。
<?>
类似,但不是将规则应用于自己的最终结果,而是将规则应用于另一个容器,因此它不再是循环的。