这个问题始于
SML.NET可以做仿函数并使用Microsoft .NET.
*请参阅:SML.NET用户指南第4.8.2节类类型和仿函数?
由于Microsoft .NET的一些限制,我一直看到F#无法做真正的仿函数.
*ML仿函数可以用.NET完全编码(C#/ F#)吗?
*算子的任何解决方法?
那么如果SML.NET可以在.NET上运行仿函数那么为什么F#不能呢?SML.NET做了什么,F#不能做什么?
我越了解来自类别理论的仿函数,我越看到它们的美丽,并希望在F#中拥有它们.
编辑
在许多文章中我都读过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)
请澄清.
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.但在这个表达中,我感到迷茫.
我对(>>=)Haskell中绑定函数的定义有一些疑问.
因为Haskell是一种纯语言,所以我们可以使用Monad来处理带副作用的操作.我认为这个策略是有点像把所有的动作可能会引起副作用另一个世界,我们可以从"纯"哈斯克尔世界虽然控制它们do或>>=.
所以当我看一下>>=函数的 定义时
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
它需要一个(a -> m b)函数,因此m a前一个动作的结果可以"解包"到非monadic a中>>=.然后,该功能(a -> m b)需要a作为其输入和返回另一个单子m b作为其结果.通过绑定功能,我可以对monadic进行操作,而不会给纯haskell代码带来任何副作用.
我的问题是为什么我们使用一个(a -> m b)函数?在我看来,一个m a -> m b函数也可以做到这一点.有什么理由,还是因为它的设计是这样的?
编辑
从意见,我知道这是很难提取a的m a.但是,我认为我可以将monadic m a视为a副作用.
是否有可能假设函数m a -> m b …
假设我们有一个一元序列:
doSomething = do
a <- f
b <- g
c <- h
pure (a, b, c)
Run Code Online (Sandbox Code Playgroud)
我们可以使用 applicative functor 轻松地重写它:
doSomething2 = (,,) <$> f <*> g <*> h
Run Code Online (Sandbox Code Playgroud)
但是如果 monadic 序列看起来像这样:
doSomething' n = do
a <- f n
b <- g a
c <- h b
pure (a, b, c)
Run Code Online (Sandbox Code Playgroud)
还有可能在那里使用 applicative 吗?如果不是,障碍是什么?(还有一本书写的,尽管如此,我们可以使用 applicative 和join一起使用,但我不知道如何使用)。
我的问题是haskell中的monad是否真的保持了hakell的纯度,如果是的话.我经常读到副作用是如何不纯的,但有用的程序(例如i/o)需要副作用.在下一句中,声明haskell的解决方案是monads.然后monad在某种程度上被解释,但实际上并不是他们如何解决副作用问题.
我已经看到了这个和这个,我对答案的解释实际上就是我自己读到的那个 - IO monad的"动作"不是i/o本身,而是执行时执行的对象/ O.但是我发现可以为任何代码或任何已编译的可执行文件创建相同的参数.难道你不能说C++程序只在编译代码执行时产生副作用吗?所有的C++都在IO monad中,所以C++是纯粹的?我怀疑这是真的,但我老实说不知道它不是以什么方式存在.事实上,Moggi(sp?)最初是否使用monads来模拟命令式程序的指称语义?
一些背景:我是haskell和函数式编程的粉丝,我希望随着我的学习继续学习更多.例如,我理解参考透明度的好处.这个问题的动机是我是一名研究生,我将为编程语言课提供2个1小时的演示文稿,其中一个特别涉及haskell,另一个涉及函数式编程.我怀疑大多数班级不熟悉函数式编程,可能已经看过一些方案.我希望能够(合理地)清楚地解释monad如何解决纯度问题而不进入类别理论和monad的理论基础,我没有时间去讨论,无论如何我不完全了解自己 - 当然还不够好.
我想知道在这种情况下"纯度"是不是真的很明确?
我正在提供这个问题的答案,我想到了使用Contmonad 的想法.我不知道Haskell足以解释为什么这个程序不起作用
import Control.Monad.Cont
fib1 n = runCont (slow n) id
where
slow 0 = return 0
slow 1 = return 1
slow n = do
a <- slow (n - 1)
b <- slow (n - 2)
return a + b
main = do
putStrLn $ show $ fib1 10
Run Code Online (Sandbox Code Playgroud)
错误 -
main.hs:10:18: error:
• Occurs check: cannot construct the infinite type: a2 ~ m a2
• In the second argument of ‘(+)’, namely ‘b’ …Run Code Online (Sandbox Code Playgroud) 这个问题与这篇文章有关:Understanding do notation for simple Reader monad: a <- (*2), b <- (+10), return (a+b)
我不在乎一种语言是否难以理解,如果它有望解决一些易于理解的语言给我们带来的问题。我被承诺在 Haskell(和其他函数式语言)中不可能改变状态是一个游戏规则改变者,我确实相信这一点。我的代码中有太多与状态相关的错误,我完全同意这篇文章,即在 OOP 语言中对对象的交互进行推理几乎是不可能的,因为它们可以改变状态,因此为了推理代码,我们应该考虑这些状态的所有可能排列。
但是,我发现对 Haskell monad 的推理也非常困难。正如您在我链接的问题的答案中所见,我们需要一个大图来理解 do 符号的 3 行。>>=为了理解代码,我总是打开stackit.io手动去糖化do符号并一步一步地编写do符号的应用程序。
这个问题或多或少是这样的:在大多数情况下,当我们有S a >>= f我们必须展开a从S并应用f它。然而,f实际上在形式中或多或少是另一回事S a >>= g,我们也必须解开等等。人脑不是那样工作的,我们不能轻易地把这些东西应用到头脑中然后停下来,把它们放在大脑的堆栈中,然后继续应用剩下的东西,>>=直到我们到达终点。当到达终点时,我们将所有这些东西存储在大脑的堆栈中并将它们粘合在一起。
因此,我一定是做错了什么。必须有一种简单的方法来理解>>=大脑中的“成分”。我知道 do 表示法非常简单,但我只能将其视为一种轻松编写>>=作文的方法。当我看到do符号时,我只是将它翻译成一堆 >>=. 我不认为它是理解代码的一种单独方式。如果有办法,我希望有人告诉我。
所以问题是:如何阅读do符号?