p*****2 发帖数: 21240 | 1 eclipse 支持吗?
如果想print点东西就要上IO Monad, 感觉很不方便呀。 |
x***4 发帖数: 1815 | 2 用trace之类的。
【在 p*****2 的大作中提到】 : eclipse 支持吗? : 如果想print点东西就要上IO Monad, 感觉很不方便呀。
|
p*****2 发帖数: 21240 | 3
先说说好用吗?不好用我就不花时间研究了。
【在 x***4 的大作中提到】 : 用trace之类的。
|
x***4 发帖数: 1815 | 4 简单的说就是把每一个function 的input和output的结果都显示出来。
这点和非functional的语言不同,一般不用step over, step into这种调试。
【在 p*****2 的大作中提到】 : : 先说说好用吗?不好用我就不花时间研究了。
|
p*****2 发帖数: 21240 | 5
好。有时间试试。多谢。
【在 x***4 的大作中提到】 : 简单的说就是把每一个function 的input和output的结果都显示出来。 : 这点和非functional的语言不同,一般不用step over, step into这种调试。
|
p*****2 发帖数: 21240 | 6 大牛看看为什么hs推断不出来类型?
data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show)
test = show EmptyTree
No instance for (Show a0) arising from a use of ???show???
The type variable ???a0??? is ambiguous
Note: there are several potential instances:
instance Show a => Show (Tree a)
-- Defined at /Users/gzhao/Documents/workspace/hsTest2/src/Tree.hs:3
:62
instance Show Double -- Defined in ???GHC.Float???
instance Show Float -- Defined in ???GHC.Float???
...plus 25 others
In the expression: show EmptyTree
In an equation for ???test???: test = show EmptyTree |
d*******r 发帖数: 3299 | 7 二爷你这个是娱乐,还是准备上公司 project? |
p*****2 发帖数: 21240 | 8
先学学,因为学scala的话,感觉还是需要学习haskell。
学的差不多的话可以看看haskell的concurrency,如果好用的话,可上。因为现在除了
node,没有什么其他语言做concurrency满意的。
【在 d*******r 的大作中提到】 : 二爷你这个是娱乐,还是准备上公司 project?
|
d*******r 发帖数: 3299 | 9 Go 的 concurrency 是如何被你 “不满意了的” :)
【在 p*****2 的大作中提到】 : : 先学学,因为学scala的话,感觉还是需要学习haskell。 : 学的差不多的话可以看看haskell的concurrency,如果好用的话,可上。因为现在除了 : node,没有什么其他语言做concurrency满意的。
|
l**********n 发帖数: 8443 | 10 akka?
【在 p*****2 的大作中提到】 : : 先学学,因为学scala的话,感觉还是需要学习haskell。 : 学的差不多的话可以看看haskell的concurrency,如果好用的话,可上。因为现在除了 : node,没有什么其他语言做concurrency满意的。
|
|
|
b********0 发帖数: 62 | 11 好像得限制一下a?
【在 p*****2 的大作中提到】 : 大牛看看为什么hs推断不出来类型? : data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show) : test = show EmptyTree : No instance for (Show a0) arising from a use of ???show??? : The type variable ???a0??? is ambiguous : Note: there are several potential instances: : instance Show a => Show (Tree a) : -- Defined at /Users/gzhao/Documents/workspace/hsTest2/src/Tree.hs:3 : :62 : instance Show Double -- Defined in ???GHC.Float???
|
p*****2 发帖数: 21240 | 12 go 不满意的是语法 落后于时代
【在 d*******r 的大作中提到】 : Go 的 concurrency 是如何被你 “不满意了的” :)
|
p*****2 发帖数: 21240 | 13 akka不好用 或者适合特定的领域 比如同通信
【在 l**********n 的大作中提到】 : akka?
|
p*****2 发帖数: 21240 | 14 把 a 限制show? 一会儿试试
【在 b********0 的大作中提到】 : 好像得限制一下a?
|
w***g 发帖数: 5958 | 15 二爷你还是别折腾haskell了。我几年前折腾过一阵haskell,没啥用还在其次,关键是
学了这个以后再看啥都不怎么顺眼了。
其实那个IO monad,本质上来说还是procedural的,不信你随便找个带网络通信的
haskell代码看,大段大段的披着functional
马甲的procedural code。下面随便贴几行用haskell写的gitlib里面的代码为证。
Monad transformer这东西我现在已经忘了怎么回事了,不过if-then-else-throw还是
直接就能看懂的。这段代码用C++/java/python哪个写都会看起来比haskell更加清楚。
copyCommit cr mref needed = do
let oid = untag cr
sha = renderOid oid
commit <- lift $ lookupCommit cr
oid2 <- parseOid sha
if HashSet.member sha needed
then do
let parents = commitParents commit
(parentRefs,needed') <- foldM copyParent ([],needed) parents
(tr,needed'') <- copyTree (commitTree commit) needed'
unless (renderObjOid (commitTree commit) == renderObjOid tr) $
throwM $ BackendError $ "Error copying tree: "
<> renderObjOid (commitTree commit)
<> " /= " <> renderObjOid tr
commit' <- createCommit (reverse parentRefs) tr
(commitAuthor commit)
(commitCommitter commit)
(commitLog commit)
mref
let coid = commitOid commit'
x = HashSet.delete sha needed''
return $ coid `seq` x `seq` (coid, x)
else return (Tagged oid2, needed)
【在 p*****2 的大作中提到】 : eclipse 支持吗? : 如果想print点东西就要上IO Monad, 感觉很不方便呀。
|
p*****2 发帖数: 21240 | 16
do确实就是语法糖,不然都用>>=麻烦死了。
我主要是觉得不学haskell的话,scala很多东西都不能理解透彻。haskell学FP比scala
应该更容易。
【在 w***g 的大作中提到】 : 二爷你还是别折腾haskell了。我几年前折腾过一阵haskell,没啥用还在其次,关键是 : 学了这个以后再看啥都不怎么顺眼了。 : 其实那个IO monad,本质上来说还是procedural的,不信你随便找个带网络通信的 : haskell代码看,大段大段的披着functional : 马甲的procedural code。下面随便贴几行用haskell写的gitlib里面的代码为证。 : Monad transformer这东西我现在已经忘了怎么回事了,不过if-then-else-throw还是 : 直接就能看懂的。这段代码用C++/java/python哪个写都会看起来比haskell更加清楚。 : copyCommit cr mref needed = do : let oid = untag cr : sha = renderOid oid
|
w***g 发帖数: 5958 | 17 当年除了FP,在系统领域还火过一个东西叫STM,现在看来也没有解决问题。
很多时候不是语言甚至算法的问题,而是问题本身或者需求本身的问题。
比如像goodbug一直推的scale out。一旦scale out以后,FP/STM解决的单机
上的concurrency问题都不成为问题了。
scala
【在 p*****2 的大作中提到】 : : do确实就是语法糖,不然都用>>=麻烦死了。 : 我主要是觉得不学haskell的话,scala很多东西都不能理解透彻。haskell学FP比scala : 应该更容易。
|
p*****2 发帖数: 21240 | 18
还是看应用。除了Akka,这些STM,CSP等等都是基于单机的。感觉现在确实是分布式问
题更受瞩目。普通developer会用framework就行了。不过感觉有时候如果单机并发能搞
定的话,确实也未必上distributed。很多公司的数据量没那么大,如果能充分利用
multi core的话,是很可能搞定的,而且比分布式overhead小,性能更佳。
按照我来看node的并发效果就很好,只是模式太单一,所以很想再搞一个备用。
【在 w***g 的大作中提到】 : 当年除了FP,在系统领域还火过一个东西叫STM,现在看来也没有解决问题。 : 很多时候不是语言甚至算法的问题,而是问题本身或者需求本身的问题。 : 比如像goodbug一直推的scale out。一旦scale out以后,FP/STM解决的单机 : 上的concurrency问题都不成为问题了。 : : scala
|
p***o 发帖数: 1252 | 19 multi-core有memory wall, 数据量不大但需要随机访问时不见得能跑过多机系统。
【在 p*****2 的大作中提到】 : : 还是看应用。除了Akka,这些STM,CSP等等都是基于单机的。感觉现在确实是分布式问 : 题更受瞩目。普通developer会用framework就行了。不过感觉有时候如果单机并发能搞 : 定的话,确实也未必上distributed。很多公司的数据量没那么大,如果能充分利用 : multi core的话,是很可能搞定的,而且比分布式overhead小,性能更佳。 : 按照我来看node的并发效果就很好,只是模式太单一,所以很想再搞一个备用。
|
a*****e 发帖数: 1700 | 20 你是用的哪个 GHC? 我在 7.4.1 和 7.8.3 都试了,正常啊?
Prelude> data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show)
Prelude> :t EmptyTree
EmptyTree :: Tree a
Prelude> show EmptyTree
"EmptyTree"
Prelude> let test = show EmptyTree
Prelude> test
"EmptyTree"
【在 p*****2 的大作中提到】 : 大牛看看为什么hs推断不出来类型? : data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show) : test = show EmptyTree : No instance for (Show a0) arising from a use of ???show??? : The type variable ???a0??? is ambiguous : Note: there are several potential instances: : instance Show a => Show (Tree a) : -- Defined at /Users/gzhao/Documents/workspace/hsTest2/src/Tree.hs:3 : :62 : instance Show Double -- Defined in ???GHC.Float???
|
|
|
a*****e 发帖数: 1700 | 21 procedural 还是 functional 不是重点,重点是两者界限清晰。SPJ 一直鼓吹
Haskell is the best imperative language. 我很赞同。
【在 w***g 的大作中提到】 : 二爷你还是别折腾haskell了。我几年前折腾过一阵haskell,没啥用还在其次,关键是 : 学了这个以后再看啥都不怎么顺眼了。 : 其实那个IO monad,本质上来说还是procedural的,不信你随便找个带网络通信的 : haskell代码看,大段大段的披着functional : 马甲的procedural code。下面随便贴几行用haskell写的gitlib里面的代码为证。 : Monad transformer这东西我现在已经忘了怎么回事了,不过if-then-else-throw还是 : 直接就能看懂的。这段代码用C++/java/python哪个写都会看起来比haskell更加清楚。 : copyCommit cr mref needed = do : let oid = untag cr : sha = renderOid oid
|
a*****e 发帖数: 1700 | 22 STM 没有解决什么问题?STM 是 composable 的,用 lock 不是。
用 STM 之后,不太容易 reason about efficiency 倒是真的。
【在 w***g 的大作中提到】 : 当年除了FP,在系统领域还火过一个东西叫STM,现在看来也没有解决问题。 : 很多时候不是语言甚至算法的问题,而是问题本身或者需求本身的问题。 : 比如像goodbug一直推的scale out。一旦scale out以后,FP/STM解决的单机 : 上的concurrency问题都不成为问题了。 : : scala
|
p*****2 发帖数: 21240 | 23
我用的eclipse,7.8.3。
【在 a*****e 的大作中提到】 : STM 没有解决什么问题?STM 是 composable 的,用 lock 不是。 : 用 STM 之后,不太容易 reason about efficiency 倒是真的。
|
p*****2 发帖数: 21240 | 24
STM到底用的广吗?
【在 a*****e 的大作中提到】 : STM 没有解决什么问题?STM 是 composable 的,用 lock 不是。 : 用 STM 之后,不太容易 reason about efficiency 倒是真的。
|
a*****e 发帖数: 1700 | 25 主要是 Haskell 和 Scala 的人在用吧,这和 STM 在 imperative language 里面的实
现不够 sound 有关,也是推广起来的一大障碍。
现在的 CPU 支持一定的 Hardware STM,虽说和 software STM 差别挺大,但是需要用
到的地方(比如用来实现 Concurrent Garbage Collector),起码用起来效率没问题。
【在 p*****2 的大作中提到】 : : STM到底用的广吗?
|
a*****e 发帖数: 1700 | 26 你写成:
test = show (EmptyTree :: Tree ())
就可以编译通过。这个类型错误的原因是,如果不加类型注释,那么推导出来的是
test = show (EmptyTree :: Show a => Tree a) :: String
这个编译通不过,是因为类型变量 a 不是一个 concrete type,且最终的 test 类型
里不包含这个变量。简单的解决方法就是任选一个满足 Show a 的 concrete type,比
如 () 类型。要么程序员把这个选择写出来,要么编译器替你挑一个。在 type class
的声明里面可以用 default 关键字来注明这个选择,但显然 Show 这个 class 里面没
有提供这样的 default。所以原程序编译通不过。
至于为什么在 GHCi 里面直接敲进去反而可以了,我也很奇怪... 已经帮你去问了。
【在 p*****2 的大作中提到】 : : STM到底用的广吗?
|
p*****2 发帖数: 21240 | 27
class
多谢大牛。大牛是用Haskell在工作上,还是自己玩呢?
另外 下边的类型定义,可以限定 a 是 Show 吗? 我翻了书,没找到相关语法。
data Tree a = EmptyTree | Node a (Tree a) (Tree a)
【在 a*****e 的大作中提到】 : 你写成: : test = show (EmptyTree :: Tree ()) : 就可以编译通过。这个类型错误的原因是,如果不加类型注释,那么推导出来的是 : test = show (EmptyTree :: Show a => Tree a) :: String : 这个编译通不过,是因为类型变量 a 不是一个 concrete type,且最终的 test 类型 : 里不包含这个变量。简单的解决方法就是任选一个满足 Show a 的 concrete type,比 : 如 () 类型。要么程序员把这个选择写出来,要么编译器替你挑一个。在 type class : 的声明里面可以用 default 关键字来注明这个选择,但显然 Show 这个 class 里面没 : 有提供这样的 default。所以原程序编译通不过。 : 至于为什么在 GHCi 里面直接敲进去反而可以了,我也很奇怪... 已经帮你去问了。
|
a*****e 发帖数: 1700 | 28
我做编译器相关工作,有时会用到 Haskell。
你如果用 deriving Show,那么会自动生成 Show a => Show (Tree a) 的 instance.
如果你想直接在类型上限定,可以写成:
data Tree a where
EmptyTree :: Tree a
Node :: a -> Tree a -> Tree a
这种写法和上面写法等价,是引入 GADT 之后加入的语法。然后,要做 Show a 的限制
就很简单了:
data Tree a where
EmptyTree :: Show a => Tree a
Node :: Show a => a -> Tree a -> Tree a
之前你遇到那个类型错误,询问结果是,可以用 {-# LANGUAGE ExtendedDefaultRules
#-} 来规避。详见
https://www.haskell.org/ghc/docs/7.8.3/html/users_guide/interactive-
evaluation.html#extended-default-rules
【在 p*****2 的大作中提到】 : : class : 多谢大牛。大牛是用Haskell在工作上,还是自己玩呢? : 另外 下边的类型定义,可以限定 a 是 Show 吗? 我翻了书,没找到相关语法。 : data Tree a = EmptyTree | Node a (Tree a) (Tree a)
|
w***g 发帖数: 5958 | 29 简单做做算术就知道。Lock是实现预防,overhead是L,每次运算都需要,所以概率为1.
总的来说overhead为L. L随着concurrency的增加非常慢,可以认为是
常数。对于单个lock来说,系统吞吐量基本上就是硬件所能支持的上限U减去overhead
: U - L。硬件用足后即使再增加线程,吞吐量基本上不会有太大的下降。
STM是事后补救,overhead是S. S和具体需要rollback和重算的内容有关。
STM失败的概率p随着concurrency的增加而增加. 平均下来每次成功
以前需要重试的次数为p/(1-p),开销为 S*p/(1-p)。这个概率随着p->1会无限增大。
所以STM在线程数增加到一定程度会出现类似硬盘thrashing的情况,系统吞吐量最终会
下降到0。现在的CPU的线程数还没那么多,所以这点还没体现出来。
STM还有一个实际问题就是transaction比较大,并且线程数>>物理线程数的时候
会出问题。如果一个transaction还没完就因为时间片用完被切换下来,那么
这个transation成功的概率就会极大地减少。这个可以通过OS或者线程库的支持
来避免,但目前这种支持似乎没怎么见到过。
在高并发下lock比STM更加有性能保障。我不觉得STM解决了什么问题。
可能在一些特殊情况下有用吧。学术界的人都会自觉不自觉地拿一些没啥用的
东西出来骗人。没办法,不往牛B里说paper根本发不出来,也拿不到钱。
【在 a*****e 的大作中提到】 : STM 没有解决什么问题?STM 是 composable 的,用 lock 不是。 : 用 STM 之后,不太容易 reason about efficiency 倒是真的。
|
p*****2 发帖数: 21240 | 30 明白了 太感谢了
.
【在 a*****e 的大作中提到】 : : 我做编译器相关工作,有时会用到 Haskell。 : 你如果用 deriving Show,那么会自动生成 Show a => Show (Tree a) 的 instance. : 如果你想直接在类型上限定,可以写成: : data Tree a where : EmptyTree :: Tree a : Node :: a -> Tree a -> Tree a : 这种写法和上面写法等价,是引入 GADT 之后加入的语法。然后,要做 Show a 的限制 : 就很简单了: : data Tree a where
|
|
|
a*****e 发帖数: 1700 | 31 你说的这个重试的问题,用 lock 也是有的。Lock contention 是个很常见的问题,带
来的性能下降也并是不像你说的线性关系,要考虑到现代 CPU 的设计的局限性。
Lock 的主要问题是稍微复杂点的程序,连正确性往往都无法保证,non-composable 从
表面上看上是个 engineering 的障碍,但为了确保正确性却需要 formal proof。做
proof 如果不能够利用 composable 的系统结构,基本上就是不可能的任务。STM 就很
好地解决了这个问题。也许你的工作中不需要考虑这些,但也不能否认 Lock 所带来的
问题是确实存在的。
无论是 Lock 和 STM 都不是万能的,它们的优势和局限性都很明显。在没有更好的解决
方案出来之前,只能说是 choose your pill 啦。
为1.
overhead
【在 w***g 的大作中提到】 : 简单做做算术就知道。Lock是实现预防,overhead是L,每次运算都需要,所以概率为1. : 总的来说overhead为L. L随着concurrency的增加非常慢,可以认为是 : 常数。对于单个lock来说,系统吞吐量基本上就是硬件所能支持的上限U减去overhead : : U - L。硬件用足后即使再增加线程,吞吐量基本上不会有太大的下降。 : STM是事后补救,overhead是S. S和具体需要rollback和重算的内容有关。 : STM失败的概率p随着concurrency的增加而增加. 平均下来每次成功 : 以前需要重试的次数为p/(1-p),开销为 S*p/(1-p)。这个概率随着p->1会无限增大。 : 所以STM在线程数增加到一定程度会出现类似硬盘thrashing的情况,系统吞吐量最终会 : 下降到0。现在的CPU的线程数还没那么多,所以这点还没体现出来。 : STM还有一个实际问题就是transaction比较大,并且线程数>>物理线程数的时候
|