免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 三月廿七
打印 上一主题 下一主题

多重继承才是符合正常逻辑的, 接口不是, 接口很扭曲 [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
1 [报告]
发表于 2012-06-17 15:08 |显示全部楼层
回复 36# fergon

monad…… 难得其实是那个名字

高级使用,monad transform神马的…… 最近被卡在array上…… 没有研究……
就只看一些常用的monad instance的话,其实monad class的两个最重要成员的签名已经可以说明它是做啥的了……

  1. return :: Monad m => a -> m a
  2. (>>=) :: Monad m => m a -> (a -> m b) -> m b
复制代码
一旦用return将类型为a的x提升到类型m a的附带有context的x'中(无论是自己使用return附带的,还是从别处获得的带有context的value),就再也没法通过Monad的method重新取回原值x。
Monad的另外两个method也是不行的:

  1.   (>>) :: m a -> m b -> m b
  2.   fail :: String -> m a
复制代码
唯一能做的,就是通过bind(>>=)。通过它的第2个参数 —— 一个函数 —— 第1个参数取回,并进行一些计算。
并且计算的结果不能是"裸"的值,是有限制的: >>= 的第1参数是 m a (m是type constructor) , 那么第2参数的返回类型(也是>>=的返回类型)必须是同一个type constructor m。
用类型系统保证不能让普通的类型a从Monad中逃逸(escape)出去,至少是没法通过Monad methods完成。
于是具体的Monad instance就了解用户只能通过的>>=来获取其内容,于是就可以在其中动一些手脚了……


于是这货就可以用来来解决IO了……
IO(ghc实现里)会附带一些primitive,以约束>>=的求值的严格性、顺序。

比如:

  1. getLine :: IO String
复制代码
用户没法获取这个String,除非通过>>=:

  1. getLine >>= (\s -> return (map toUpper s)) :: IO [Char]
复制代码
或者写成point free:

  1. getLine >>= return . map toUpper :: IO [Char]
复制代码
注意return, 再次将结果提升到IO monad之中,避免该值被直接获取。 而如果不用return, map toUpper 就不符合>>=的签名。

为了获取大写的string,唯一能做的是再次>>=,比如这次就输出了:

  1. putStr :: String -> IO ()
  2. getLine >>= return . map toUpper >>= putStr :: IO ()
复制代码
又或者将那个return省掉,直接:

  1. getLine >>= putStr . map toUpper :: IO ()
复制代码
最终,haskell程序就是要这样组合出一个main :: IO a, 比如:

  1. main = getLine >>= putStr . map toUpper
复制代码
程序就是对main求值,得到a,并舍弃其结果(仅为了副作用)。
整个过程中,IO a -> a都是被控制在:
1.  >>= 的第2个参数里
2. 对main的求值
于是IO实现>>=时就可以保证 getLine/putStr一定会发生且仅一次,并且getLine一定在putStr之前。(并且对main稍微再动点手脚……)


当然,并不是真的没法从m a中逃逸得到a。通过Monad methods不行,但具体的Monad instance是可以的。
IO的话,可以pattern match(或者case)它的data constructor:

  1. newtype IO a
  2.   = GHC.Types.IO (GHC.Prim.State# GHC.Prim.RealWorld
  3.                   -> (# GHC.Prim.State# GHC.Prim.RealWorld, a #))
复制代码
但这应该被认为是private的,就像很多支持private的语言里即使有获取private的方法也应该当作不知道。
另外还有一套公开的:

  1. System.IO.Unsafe.unsafePerformIO :: IO a -> a
  2. -- 这个module里还有一些
复制代码
但这时候程序员就要自己保证如果求值被省略(甚至多次)与改变顺序也会得到希望的结果。


另外的一些具体的monad instance的逃逸就是公开的了…… runST, (case a of Just x -> ...; Nothing -> ...), xs !! idx 等等……
而且它们对>>=的含义也不一定是用于限制求值顺序了。
比如Maybe,只要其中有一个是Nothing,整个bind链的结果就是Nothing。
list就用作这样的事情:

  1. "ab" >>= \ x -> [toLower x,toUpper x] -- > "aAbB"
  2. concat [ [toLower x, toUpper x] | x <- "ab" ] -- > "aAbB"
复制代码
总之,Monad class就只描述了那2个(把fail算上就是3个吧)member。
具体的Monad instance能干什么…… 就可以发挥你的想象了……  你让它做什么,它就是什么……  当然,有个monad law的……


附带一点材料……
我是从 http://learnyouahaskell.com/a-fistful-of-monads 开始,感觉终于可以用这货了……
这书前面部分有点无聊(类容简单、还配一些很花哨的图……) 所以之前的感觉是这书不咋嘀……
但耐心看过一次后,尤其要看前一章就有悟了的感觉。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
2 [报告]
发表于 2012-06-17 15:25 |显示全部楼层
回复 27# sonicling

还有这一层原因?不过对于Javaer来说,效率算什么,可以吃吗?

反正对待"多继承在java中是不需要的"言论时,我就用:
http://docs.oracle.com/javase/6/ ... /MouseListener.html
http://docs.oracle.com/javase/6/ ... t/MouseAdapter.html
去扇他脸,十拿九稳。除非是城墙脸。又或者只要是Gosling喷的,哪怕是坨屎都是香的,那真是没得救。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP