Monad通常用return和来解释bind.不过,我猜想你也可以实现bind在以下方面join(和fmap?)
在缺乏一流功能的编程语言中,使用起来bind非常难以捉摸.join另一方面,看起来很容易.
但是,我并不完全确定我理解它是如何join运作的.显然,它有[Haskell]类型
join :: Monad m => m (m x) -> m x
对于monad列表,这显然很简单concat.但是对于一般的monad来说,这种方法在操作上实际上做了什么?我看到它对类型签名的作用,但我试图弄清楚我是如何在Java或类似的东西中写出这样的东西.
(实际上,这很容易:我不会.因为仿制药已经坏了.;-)但原则问题仍然存在......)
哎呀.看起来之前有人问过:
可能有人勾画出使用普通的单子一些实现return,fmap和join?(即,根本没有提到>>=.)我想也许这可能有助于它沉入我愚蠢的大脑......
我刚才读从以下typeclassopedia约之间的差异Monad和Applicative.我能理解,没有join在Applicative.但是下面的描述看起来含糊不清,我无法弄清楚monadic计算/动作的"结果"究竟是什么意思.所以,如果我把一个值放入Maybe,这使得一个monad,这个"计算"的结果是什么?
让我们更仔细地看一下(>> =)的类型.基本的直觉是它将两个计算组合成一个更大的计算.第一个参数ma是第一个计算.但是,如果第二个论点只是一个mb,那将是无聊的; 那么计算就无法相互交互(实际上,这正是Applicative的情况).因此,(>> =)的第二个参数具有类型a - > mb:这种类型的函数,给定第一次计算的结果,可以产生第二个要运行的计算....直观地说,正是这种能力使用先前计算的输出来决定接下来运行哪些计算使Monad比Applicative更强大.应用计算的结构是固定的,而Monad计算的结构可以基于中间结果而改变.
是否有一个具体的例子说明"能够使用先前计算的输出来决定接下来要运行的计算",Applicative没有?
在许多文章中我都读过monad >>=运算符是一种表示函数组合的方法.但对我来说,它更接近某种高级功能应用程序
($) :: (a -> b) -> a -> b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
对于我们的构图
(.) :: (b -> c) -> (a -> b) -> a -> c
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
Run Code Online (Sandbox Code Playgroud)
请澄清.
我是函数式编程的新手(来自javascript),我很难分辨两者之间的区别,这也搞砸了我对functor与monads的理解.
仿函数:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
Monad(简化):
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
fmap 接受函数和仿函数,并返回一个仿函数.>>= 接受一个函数和一个monad,并返回一个monad.两者之间的区别在于函数参数:
fmap - (a -> b)>>= - (a -> m b)>>=获取一个返回monad的函数参数.我知道这很重要,但是我很难看到这个轻微的东西如何使monad比functor强大得多.谁能解释一下?
我看到处处Applicative可以处理副作用,但我见过的所有简单例子都是将各种东西组合在一起,如:
> (,,) <$> [1,2] <*> ["a", "b", "c"] <*> ["foo", "bar"]
[(1,"a","foo"),(1,"a","bar"),(1,"b","foo"),(1,"b","bar"),
(1,"c","foo"),(1,"c","bar"),(2,"a","foo"),(2,"a","bar"),
(2,"b","foo"),(2,"b","bar"),(2,"c","foo"),(2,"c","bar")]
Run Code Online (Sandbox Code Playgroud)
哪个很酷,但我看不出它与副作用有何联系.我的理解是,它Applicative是一个弱单子,所以你可以处理副作用(就像你对State monad一样),但你不能重复使用前一个副作用的结果.
这是否意味着>>可以写出Applicative类似的东西
do
print' "hello"
print' "world"
Run Code Online (Sandbox Code Playgroud)
会有意义(有print' :: a -> Applicative something)(使用适当的do-applicative扩展名).
在另一个世界,之间的区别Monad,并Applicative是Monad允许x <- ...,但Applicative没有.
然后,是作家monad,只是一个应用程序?
我对Haskell非常陌生,对语言的"架构"印象深刻,但是我仍然困扰着monad是如何纯粹的.
由于你有任何指令序列,它使它成为一个不纯的函数,尤其是 I/O函数从任何角度来看都不是纯粹的.
是因为Haskell像所有纯函数一样假设IO函数也有返回值,但是以操作码的形式还是什么?我真的很困惑.
class Applicative f => Monad f where
return :: a -> f a
(>>=) :: f a -> (a -> f b) -> f b
Run Code Online (Sandbox Code Playgroud)
(<*>)可以源自纯粹和(>>=):
fs <*> as =
fs >>= (\f -> as >>= (\a -> pure (f a)))
Run Code Online (Sandbox Code Playgroud)
对于线
fs >>= (\f -> as >>= (\a -> pure (f a)))
Run Code Online (Sandbox Code Playgroud)
我很困惑的用法>>=.我认为它需要一个仿函数f a和一个函数,然后返回另一个仿函数f b.但在这个表达中,我感到迷茫.
在java中我们总是写:
public static void main(String[] args){...}
Run Code Online (Sandbox Code Playgroud)
当我们想要开始编写程序时.
我的问题是,对于Haskell,IE是否相同:我是否总是可以确定声明:main = do,当我想在Haskell中为程序编写代码时?
例如:
main = do
putStrLn "What's your name?"
name <- getLine
putStrLn ("Hello " ++ name)
Run Code Online (Sandbox Code Playgroud)
该程序将询问用户"你叫什么名字?" 然后,用户输入将存储在name-variable中,并且在程序终止之前将显示"Hello"++名称.
假设我有两个功能
f :: Monad m => a -> m a
g :: a -> a
Run Code Online (Sandbox Code Playgroud)
我想连续应用于某些元素,如下所示:
(return x) >>= f >>= g
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为 g 是纯的,所以我首先需要“人为地”将它变成 monadic。一种可能性是
(return x) >>= f >>= (return . g)
Run Code Online (Sandbox Code Playgroud)
这对我来说不是很直观。另一种可能性是使用 Monad 是 Applicative:
(return g) <*> ((return x) >>= f)
Run Code Online (Sandbox Code Playgroud)
但这不是很直观,因为函数和参数的顺序不同:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
处理这个问题的规范方法是什么?如果(>>==) = (flip …
这是 kleisli 组合的常见实现:
kleisli :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
kleisli = \f g x -> f x >>= g
Run Code Online (Sandbox Code Playgroud)
为什么它不期望 monadic 上下文中的值呢?我相信有一个很好的理由。我只是没能看到它。
kleisli' :: Monad m => (a -> m b) -> (b -> m c) -> m a -> m c
kleisli' = \f g x -> x >>= f >>= g
Run Code Online (Sandbox Code Playgroud)
该类型似乎更易于组合,并且return可以在调用站点上只有纯值的情况下使用。
假设我有两个函数f,g它们都接受常规值并返回一个Either像这样的值:
g :: a -> Either x b
f :: b -> Either x c
Run Code Online (Sandbox Code Playgroud)
我如何将两者链接在一起以获得类似的东西f . g?
我想出的最佳解决方案是创建一个名为的辅助函数applyToRight,其工作方式如下
applyToRight :: (a -> Either x b) -> Either x a -> Either x b
applyToRight f x =
case x of
Left a -> Left a
Right b -> f b
Run Code Online (Sandbox Code Playgroud)
这样我就可以做
applyToRight f (g a)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我专门谈论Either,但我认为这个问题可以推广到所有应用函子。处理这个问题的最优雅的方法是什么?
haskell composition functor function-composition applicative
Applicative 通常表现为一种将多参数函数提升为函子并将函子值应用于它的方法。但我想知道是否有一些微妙的额外功能源于它可以通过提升返回函数的函数并一次应用一个函数参数来实现这一点。
想象一下,我们定义了一个基于提升函数的接口,其参数是一个参数元组:
# from Functor
fmap :: (a -> b) -> Fa -> Fb
# from Applicative
pure :: a -> Fa
# combine multiple functor values into a functor of a tuple
tuple1 :: Fa -> F(a)
tuple2 :: Fa -> Fb -> F(a,b)
tuple3 :: Fa -> Fb -> Fc -> F(a,b,c)
(etc ...)
# lift multi-argument functions (that take a tuple as input)
ap_tuple1 :: ((a) -> b) -> F(a) -> Fb
ap_tuple2 :: ((a,b) -> …Run Code Online (Sandbox Code Playgroud) haskell ×12
monads ×9
applicative ×5
functor ×3
composition ×2
bind ×1
do-notation ×1
kleisli ×1