我有以下代码:
import Control.Monad
coin :: MonadPlus m => m Int
coin = return 0 `mplus` return 1如果我在解释器上计算coin :: Maybe Int,它就会计算Just 0。这是正常的,因为可能是作为MonadPlus的实例实现的。
如果我在解释器上计算coin :: [Int],它会打印[0, 1],因为列表中mplus的实现是一个append。
但是如果我评估coin,没有任何类型的装饰器,它会打印0。为什么?解释器‘转换’coin来计算它的类型是什么?
此代码从:http://homes.sice.indiana.edu/ccshan/rational/S0956796811000189a.pdf提取。
发布于 2018-10-28 13:28:18
是的,这不是一个有很好记录的地方。当您在ghci中输入一个表达式时,它使用表达式的类型来决定要做什么:
IO ():运行操作,不要做进一步的操作。Show a => IO a:运行操作并print结果。IO a:运行操作,不再做进一步的操作。print包装整个表达式。它是如何决定这些东西的哪种类型的?简单:它试图统一您的表达式的类型,每个签名依次解决所有由此产生的约束。(对于智囊团来说:这是对延长的违约规则的补充!这解释了为什么它似乎在默认m,尽管标准的默认规则和扩展的默认规则都没有说明使用什么默认值。)
因此,由于表达式不与IO ()统一,而是与Show a => IO a统一,因此ghci在统一过程中查找m ~ IO (和a ~ Int),发现存在一个MonadPlus IO (和Show Int)实例来解决约束,运行您的操作并打印结果。
发布于 2018-10-28 13:24:58
在没有指定其他签名的情况下,GHCi (但一般不是GHC )将尽可能地专门针对IO的多态类型构造函数。提示符下的IO操作依次被执行并将其结果以单元方式绑定到it变量,只要结果类型(cf )有一个Show实例,该变量就会被打印(即do { it <- action; print it })。Daniel Wagner's answer)。有关更多细节,请参阅“用户指南”的https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#i-o-actions-at-the-prompt和https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#the-it-variable部分。
在您的具体案例中,发生了IO。您可以从中获得return 0,因为mplus for IO只在第一个操作抛出异常时执行第二个操作。一次示范:
GHCi> readLn `mplus` readLn :: IO Integer
0
0
GHCi> readLn `mplus` readLn :: IO Integer
foo
1
1
GHCi> readLn `mplus` readLn :: IO Integer
foo
bar
*** Exception: user error (Prelude.readIO: no parse)https://stackoverflow.com/questions/53031608
复制相似问题