如果在正常化时信息丢失,monad如何确定排序?

Mai*_*tor 0 monads haskell

如果我理解正确,a monad只是绑定>>=return运算符遵循某些规则的实现,这些规则基本上组成了不同返回类型的2个函数.因此,例如,那些是等价的:

putStrLn "What is your name?"
>>= (\_ -> getLine)
>>= (\name -> putStrLn ("Welcome, " ++ name ++ "!"))

(bind (putStrLn "What is your name?")
      (bind
          (\_ -> getLine)
          (\name -> putStrLn ("Welcome, " ++ name ++ "!"))))
Run Code Online (Sandbox Code Playgroud)

但是如果我们强烈地规范化这个表达式,最终的结果就是:

(putStrLn ("Welcome, " ++ getline ++ "!"))
Run Code Online (Sandbox Code Playgroud)

第一个陈述(putStrLn "What is your name?")完全丢失了.此外,getLine看起来像一个没有参数的函数,这是无稽之谈.那么这是如何工作的,以及函数的实际定义是什么?>>=return

J. *_*son 12

你的逻辑错误是你假设某些减少规则不会.特别是,您似乎正在使用

f >>= (\x -> g x)  ====  g f
Run Code Online (Sandbox Code Playgroud)

如果这样,那么,monads将是非常愚蠢的:(>>=)只是flip ($).但总的来说,它根本不存在.事实上,它没有成功的原因是为monad提供了一个有趣的机会.


为了进一步探索,这里是一个(>>=) == flip ($)(基本上)持有的monad .

newtype Identity a = Identity { unIdentity :: a }
Run Code Online (Sandbox Code Playgroud)

为了使我们的方程式成功,我们必须使用它Identity a ~ a.显然,这并非严格意义,但让我们假装.特别是,Identity . unIdentity并且unIdentity . Identity都是身份,无操作,我们可以自由地应用Identity或者unIdentity我们喜欢使类型匹配

instance Functor Identity where
  fmap f (Identity a) = Identity (f a)

instance Monad Identity where
  return a = Identity a          -- this is a no-op
  ida >>= f = f (unIdentity ida)
Run Code Online (Sandbox Code Playgroud)

现在,我们要特别考察

ida :: Identity a
f   :: a -> b

ida >>= Identity . f          :: Identity b
===
Identity (f (unIdentity ida)) :: Identity b
Run Code Online (Sandbox Code Playgroud)

如果我们扔掉Identity/ unIdentity噪音,从而产生ida = Identity a一些知识

Identity (f (unIdentity ida)) :: Identity b
===
Identity (f a)                :: Identity b
===                              ~
f a                           ::          b
Run Code Online (Sandbox Code Playgroud)

因此,虽然(>>=) == flip ($)形成了直觉的某种基础(>>=)......在任何比Identitymonad(和所有其他monad都更有趣)更有趣的情况下,它并不完全正确.