Kam*_*mel 12 monads haskell functional-programming category-theory
join
定义bind
以将组合数据结构展平为单个结构.
从类型的系统视图,(+) 7 :: Num a => a -> a
可被视为一个Functor
,(+) :: Num a => a -> a -> a
可以被认为是一个Functor
的Functor
,如何获得一些关于它的直觉,而不是仅仅依靠类型系统?为什么join (+) 7 === 14
?
即使可以通过函数绑定过程手动步进来获得最终结果,但如果给出一些直觉,那将是很好的.
这是来自NICTA演习.
-- | Binds a function on the reader ((->) t).
--
-- >>> ((*) =<< (+10)) 7
-- 119
instance Bind ((->) t) where
(=<<) ::
(a -> ((->) t b))
-> ((->) t a)
-> ((->) t b)
(f =<< a) t =
f (a t) t
-- | Flattens a combined structure to a single structure.
--
-- >>> join (+) 7
-- 14
join ::
Bind f =>
f (f a)
-> f a
join f =
id =<< f
*Course.State> :t join (+)
join (+) :: Num a => a -> a
*Course.State> :t join
join :: Bind f => f (f a) -> f a
*Course.State> :t (+)
(+) :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)
dup*_*ode 10
如何获得一些直觉而不仅仅依靠类型系统?
我宁愿说依赖类型系统是构建特定直觉的好方法.类型join
是:
join :: Monad m => m (m a) -> m a
Run Code Online (Sandbox Code Playgroud)
专门(->) r
,它变成:
(r -> (r -> a)) -> (r -> a)
Run Code Online (Sandbox Code Playgroud)
现在让我们尝试定义join
函数:
-- join :: (r -> (r -> a)) -> (r -> a)
join f = -- etc.
Run Code Online (Sandbox Code Playgroud)
我们知道结果必须是一个r -> a
函数:
join f = \x -> -- etc.
Run Code Online (Sandbox Code Playgroud)
但是,我们不知道在所有关于什么什么r
和a
类型,因此,我们知道没有什么讲究f :: r -> (r -> a)
和x :: r
.我们的无知意味着我们可以用它们做一件事:x
作为一个论点,传递给f
和f x
:
join f = \x -> f x x
Run Code Online (Sandbox Code Playgroud)
因此,join
函数传递相同的参数两次,因为这是唯一可能的实现.当然,这种实施只是一种适当的monadic,join
因为它符合monad法则:
join . fmap join = join . join
join . fmap return = id
join . return = id
Run Code Online (Sandbox Code Playgroud)
验证这可能是另一个很好的练习.
与monad的传统类比一起作为计算的上下文,join
是一种组合上下文的方法.让我们从你的例子开始吧.join (+) 7
.使用函数作为monad意味着读者monad.(+ 1)
是一个读者monad,它采用环境并添加一个环境.因此,(+)
将是读者monad中的读者monad.外部读者monad占用环境 n
并返回表单的读者(n +)
,这将带来一个新的环境.join
简单地组合两个环境,以便您提供一次,并将给定的参数应用两次.join (+) === \x -> (+) x x
.
现在,更一般地说,让我们看看其他一些例子.该Maybe
单子代表潜在的故障.值Nothing
是计算失败,而a Just x
是成功.a Maybe
中的a Maybe
是可能失败两次的计算.价值Just (Just x)
显然是成功的,所以加入产生Just x
.A Nothing
或a Just Nothing
表示某些时候出现故障,因此加入可能的故障应该表明计算失败,即Nothing
.
可以对列表monad进行类似的类比,其join
仅仅concat
是作者monad,其使用monoidal运算符<>
来组合所讨论的输出值或任何其他monad.
join
是monad的一个基本属性,它的操作使得它比functor或applicative functor强大得多.可以映射函数,应用程序可以是序列,monad可以组合.分类地,monad通常被定义为join
和return
.碰巧的是,在Haskell中,我们发现它更方便的来定义它return
,(>>=)
和fmap
,但两人的定义已被证明的代名词.
归档时间: |
|
查看次数: |
282 次 |
最近记录: |