反向行为>> =(==)

时间:2015-09-15 17:19:50

标签: haskell

用于确定字符串是否为回文结构的函数可以通过

以无点的应用方式实现。
pal1 = (==) <$> reverse <*> id 

这是一个monadic版本

reverse >>= (==)

modadic版本如何在没有显式调用id的情况下工作?我试图使用有点函数查看有针对性的表示,并获得相同的函数。

5 个答案:

答案 0 :(得分:8)

这可以使用x -> y可以被视为一种&#34;读者monad&#34;的事实。如果我们要说

type Reader r x = r -> x

然后我们有一个Monad (Reader r)的实例。所以我们可以看到

reverse :: [x] -> [x]

实际上是

reverse :: Reader [x] [x]

类似地,

(==) :: [x] -> [x] -> Bool

可以写成

(==) :: [x] -> Reader [x] Bool

然后(>>=)将两者连接在一起。

所以......我们从reverse开始,这是一个Reader动作,它会读取一个列表并返回一个列表。然后,我们使用>>=将其传递给==,这是一个获取列表的函数,并返回Reader [x] Bool

简而言之,输入列表由Reader的操作复制,它基本上接受输入并将其传递给链中的每个函数。 (这就是读者monad 。)

我希望这有点意义......我花了一段时间才弄清楚了

答案 1 :(得分:5)

让我们看一下((->) r)的Monad实例:

instance Monad ((->) r) where
    return = const
    f >>= k = \ r -> k (f r) r

然后只需填写你的monadic代码:

reverse >>= (==) = \r -> (==) (reverse r) r

我们可以用更熟悉的方式写作:

\r -> reverse r == r

答案 2 :(得分:4)

要添加到其他答案,这是另一个POV。让我们通过fmapjoin来定义绑定:

m >>= act = join (fmap act m)

表达式(==) <$> reverse的类型为Eq a => [a] -> [a] -> Bool,相当于fmap (==) reverse。现在,我们将其传递给join :: m (m a) -> m a,对于(->) r monad实例,类型将为([a] -> [a] -> Bool) -> ([a] -> Bool)。也就是说,加入恰好是<*> id部分。

答案 3 :(得分:1)

我认为最简单的理解方法是查看类型:

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

专门针对((->) r)实例:

(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b

您没有获得a。产生一个的唯一方法是将第一个函数r -> a应用于您给出的r。生成b的唯一方法是将第二个函数应用于刚刚生成的ra。这意味着此函数 * 的唯一可能定义是:

f >>= g = \a -> g (f a) a

插入我们的论据,我们得到:

reverse >>= (==) 

-- definition of (>>=)
= \a -> (==) (reverse a) a

-- prefix to infix
= \a -> reverse a == a

参数化是推理多态函数的有力工具。

*除了底部

答案 4 :(得分:1)

其他答案确认两者的行为相同,但没有解释id实际去哪里。在这个答案中,我会尝试这样做。重点是,对于Reader,我们有一个好奇的id - 删除等式:id >>= return . f = f。 (这个等式的一个更美丽的形式是(id >>=) = (>>= id);与monad定律一起,美丽的形式暗示了易于使用的形式。)使解释更简单,而不是试图从应用形式转换为monadic形式,我会理所当然地认为你相信以下等式:

(==) <$> reverse <*> id
= { too annoying to do carefully }
reverse >>= \xs -> id >>= \ys -> return ((==) xs ys)

所以我们将从最后一行开始,到reverse >>= (==)结束。在此过程中,关键是要注意id(.)的身份 - 对于Reader monad而言恰好是fmap。我们走了:

reverse >>= \xs -> id >>= \ys -> return ((==) xs ys)
= { monad law }
reverse >>= \xs -> fmap ((==) xs) id
= { definition of fmap for Reader }
reverse >>= \xs -> (.) ((==) xs) id
= { id is the identity of fmap }
reverse >>= \xs -> (==) xs
= { eta reduction }
reverse >>= (==)

那么id >>= return . f = f的含义是什么?那么,将函数视为“索引值”,我们可以将id理解为等于其索引的值;和return是各地的价值。所以id >>= return . f说“查看索引x;然后,(仍然在索引x),返回忽略其索引并具有值f x”的值。碰巧我们忽略的索引和我们交给f的值匹配 - 所以我们也可以跳过所有的间接,简单地说“查看索引x并应用{{1对它“。这就是等式的含义。