小编JUS*_*ION的帖子

Haskell/GHC中的`forall`关键字有什么作用?

我开始理解forall关键字如何在所谓的"存在类型"中使用,如下所示:

data ShowBox = forall s. Show s => SB s
Run Code Online (Sandbox Code Playgroud)

然而,这仅仅是如何forall使用的一个子集,我根本无法将其用于这样的事情:

runST :: forall a. (forall s. ST s a) -> a
Run Code Online (Sandbox Code Playgroud)

或解释为什么这些是不同的:

foo :: (forall a. a -> a) -> (Char, Bool)
bar :: forall a. ((a -> a) -> (Char, Bool))
Run Code Online (Sandbox Code Playgroud)

或整个RankNTypes东西......

我倾向于选择清晰,无术语的英语而不是学术环境中常见的语言.我尝试阅读的大部分解释(我可以通过搜索引擎找到的解释)存在以下问题:

  1. 他们不完整.他们解释如何使用这个关键字(如"生存型")的一个组成部分这让我感到高兴,直到我读使用它在一个完全不同的方式代码(比如runST,foobar以上).
  2. 他们密集地充满了假设,我已经阅读了最新的离散数学分类,类别理论或抽象代数本周流行.(如果我再也没有读过"请参阅论文的任何细节",那就太早了.)
  3. 它们的编写方式经常将简单的概念转变为曲折的语法和语法.

所以...

关于实际问题.任何人都可以完全解释的forall清晰,简单的英语关键字(或者,如果它存在于某个地方,点到我已经错过了这样一个明确的解释),不承担我在行话悠久的数学家?


编辑添加:

下面有高质量的答案有两个突出的答案,但不幸的是我只能选择一个最好的答案. 诺曼的回答很详细的和有用的,解释的方式,表现出一定的理论基础的东西forall,并在同一时间向我展示了一些它的实际影响. yairchu的回答覆盖了其他人没有提到的范围(范围类型变量),并用代码和GHCi会话说明了所有概念.我愿意选择两者是最好的.不幸的是,我不能和上,俯瞰着两个答案后密切,我已经决定,yairchu的稍微挤掉了诺曼,因为说明性代码和附加的说明.这是一个有点不公平,但是,因为我真的需要这两个答案,了解这一点是一点forall没给我留下了恐惧的隐隐感觉,当我看到它在类型签名.

syntax haskell types ghc forall

295
推荐指数
7
解决办法
4万
查看次数

这个改组算法有什么问题,如果有的话,我怎么知道呢?

就像背景一样,我知道Fisher-Yates完美的洗牌.它的O(n)复杂性和保证的一致性是一个很好的混乱,我不会使用它...在一个允许就地更新数组的环境中(所以在大多数情况下,如果不是全部,命令式编程环境).

可悲的是,函数式编程世界并没有让你访问可变状态.

然而,由于Fisher-Yates,我没有很多关于如何设计改组算法的文献.完全解决这个问题的几个地方之前做了这么简单的说法,实际上,"所以这里是Fisher-Yates,这是你需要知道的所有洗牌".最后,我必须提出自己的解决方案.

我想出的解决方案是这样的,可以随机播放任何数据列表:

  • 如果列表为空,则返回空集.
  • 如果列表包含单个项目,则返回该单个项目.
  • 如果列表非空,则使用随机数生成器对列表进行分区,并将算法递归地应用于每个分区,然后汇总结果.

在Erlang代码中,它看起来像这样:

shuffle([])  -> [];
shuffle([L]) -> [L];
shuffle(L)   ->
  {Left, Right} = lists:partition(fun(_) -> 
                                    random:uniform() < 0.5 
                                  end, L),
  shuffle(Left) ++ shuffle(Right).
Run Code Online (Sandbox Code Playgroud)

(如果这看起来像是一种疯狂的快速排序,那么,基本上就是这就是它.)

所以这就是我的问题:同样的情况使得找到非Fisher-Yates 的改组算法变得困难,这使得找到分析混洗算法的工具同样困难.在分析PRNG的均匀性,周期性等方面,我可以找到很多文献,但没有关于如何分析洗牌的大量信息.(事实上​​,我在分析shuffle时发现的一些信息是完全错误的 - 很容易通过简单的技术欺骗.)

所以我的问题是:我如何分析我的改组算法(假设那里的random:uniform()调用可以生成具有良好特性的适当随机数)?我可以使用哪些数学工具来判断,在1 ... 100的整数列表中,是否有100,000次洗牌运行给了我合理的改组结果?我已经做了一些我自己的测试(例如,比较增量到shuffles中的减量),但我想知道更多.

如果对该混洗算法本身有任何了解,也会受到重视.

algorithm functional-programming shuffle

76
推荐指数
2
解决办法
1万
查看次数

用Java实现协同程序

这个问题与我关于Java中现有协程实现的问题有关.如果我怀疑,事实证明Java中目前没有完整的协同程序实现,那么实现它们需要什么?

正如我在那个问题中所说,我知道以下内容:

  1. 您可以在后台实现"coroutines"作为线程/线程池.
  2. 你可以在幕后用JVM字节码做一些棘手的事情,以使协同成为可能.
  3. 所谓的"Da Vinci Machine"JVM实现具有原语,使得协程可以在没有字节码操作的情况下运行.
  4. 协同程序也有各种基于JNI的方法.

我将依次解决每个人的不足之处.

基于线程的协同程序

这种"解决方案"是病态的.协同程序的重点是避免线程,锁定,内核调度等的开销.协同程序应该是轻量级的,并且只能在用户空间中执行.在具有严格限制的全倾斜螺纹方面实现它们可以消除所有优点.

JVM字节码操作

这种解决方案更实用,虽然有点难以实现.这与在C中的协同程序库中跳转到汇编语言大致相同(这是其中有多少工作),其优点是您只有一个架构可以担心并且正确.

它还将您绑定到仅在完全兼容的JVM堆栈上运行代码(例如,没有Android),除非您可以找到在非兼容堆栈上执行相同操作的方法.但是,如果您确实找到了这样做的方法,那么您现在已经将系统复杂性和测试需求翻了一番.

达芬奇机器

达芬奇机器很酷的实验,但由于它不是标准的JVM,它的功能无处不在.事实上,我怀疑大多数生产环境都会特别禁止使用达芬奇机器.因此,我可以使用它来进行很酷的实验,但不能用于我期望发布到现实世界的任何代码.

这也有类似于上面的JVM字节码操作解决方案的附加问题:将无法在替代堆栈(如Android)上工作.

JNI实施

这个解决方案在Java中实现这一点的意义重大.CPU和操作系统的每种组合都需要独立测试,每一种都是可能令人沮丧的微妙故障.或者,当然,我可以完全将自己绑定到一个平台,但这也使得用Java做事的意义完全没有实际意义.

所以...

有没有办法在不使用这四种技术之一的情况下在Java中实现协同程序?或者我会被迫使用那些闻起来最少的四个中的一个(JVM操作)?


编辑添加:

只是为了确保混乱载,这是一个相关的问题我的另外一个,但又不尽相同.那个人正在寻找一个现有的实施方案,以避免不必要地重新发明轮子.这是一个问题,如果另一个证明无法解决,将如何在Java中实现协同程序.目的是在不同的线程上保留不同的问题.

java kotlin-coroutines

63
推荐指数
3
解决办法
3万
查看次数

是否有关于Erlang解析转换的完整教程?

有许多片段详细说明了Erlang中解析变换过程的各个部分,但是我没有发现从动机到执行的完整覆盖.是否有一个很好的教程,我在某处遗漏了,如果有的话,它在哪里可以找到?

erlang parsing

42
推荐指数
1
解决办法
7216
查看次数

Java Bean和Enterprise Java Bean之间的区别?

它们是不同的还是可以互换使用?如果它们不同,那么是什么使它们彼此不同?

java ejb javabeans java-ee

42
推荐指数
3
解决办法
4万
查看次数

Java中可用的协程库

我想用Java做一些事情,如果使用并发例程编写会更清楚,但是对于哪些完全线程严重过度杀伤.当然,答案是使用协同程序,但标准Java库中似乎没有任何协程支持,而快速谷歌在这里或那里会带来诱人的提示,但没有什么实质性的.

这是我到目前为止所发现的:

  • JSIM有一个协程类,但它看起来非常重量级,并且看起来与点上的线程混淆.这样做的目的是降低全面线程的复杂性,而不是添加它.此外,我不确定该类是否可以从库中提取并独立使用.
  • Xalan有一个coroutine set类,可以执行类似coroutine的东西,但是如果可以从整个库中有意义地提取它,那么它仍然是可疑的.它看起来像是一个严格控制的线程池形式,而不是实际的协同程序.
  • 有一个谷歌代码项目看起来像我所追求的,但如果有什么它看起来比使用线程更重量级.我基本上对需要软件在运行时动态更改JVM字节码以完成其工作的事情感到紧张.这看起来有点矫枉过正,并且会像协同程序解决的那样导致更多问题.此外,它似乎没有实现整个协程概念.通过我的一瞥,它提供了一个yield只返回调用者的功能.正确的协同程序允许yields将控制权直接转移到任何已知的协程.基本上这个库,重量级和可怕的,只给你支持迭代器,而不是完全通用的协同程序.
  • 有希望命名的Coroutine for Java失败了,因为它是一个特定于平台(显然使用JNI)的解决方案.

这就是我发现的一切.

我知道Da Vinci机器中对协同程序的本机JVM支持,我也知道这样做的JNI延续技巧.然而,对我来说这些并不是一个很好的解决方案,因为我不一定能控制我的代码运行在哪个VM或平台上.(事实上​​,任何字节码操作系统都会遇到类似的问题 - 如果可能的话,最好是纯Java.运行时字节码操作会限制我在Android上使用它.例如.)

那么有人有任何指针吗?这甚至可能吗?如果没有,是否可以在Java 7中使用?


编辑添加:

只是为了确保混乱载,这是一个相关的问题我的另外一个,但又不尽相同.这个是寻找现有的实施方案,以避免不必要地重新发明轮子.另一个是关于如何在Java中实现协同程序的问题,如果这个问题无法解决的话.目的是在不同的线程上保留不同的问题.


进一步编辑添加:

答案被选中.然而,有些评论是有条理的.库指向的不是一个协程库,所以它在技术上不回答我的问题.尽管如此,它与上面链接的Google Code项目有两个优势:

  1. 两种解决方案都使用字节码操作,但所选的库允许静态字节码操作,这使得它可以在Android和其他不兼容的JVM堆栈中使用.
  2. Google Code项目不会执行完整协同程序.虽然答案的库甚至根本不做协同程序,但它确实做了一些更重要的事情:它为滚动我自己的全功能协程提供了一个很好的基础工具.

java coroutine

42
推荐指数
4
解决办法
1万
查看次数

功能语言如何模拟副作用?

由于副作用破坏了参考透明度,它们是否违背功能语言的观点?

io functional-programming referential-transparency

22
推荐指数
2
解决办法
4541
查看次数

Java中的线程

今天我在接受采访时谈到了Java中的Thread概念?问题是......

  1. 什么是线程?
  2. 我们为什么要选择线程?
  3. 线程上的实时示例.
  4. 我们可以在Spring框架服务类中创建线程吗?
  5. 可以flex一个线程吗?

除了Thread的定义之外,我没有回答任何问题,我也是从互联网上学到的.

任何人都可以清楚地向我解释这个.

更新:

线程和普通java类之间有什么区别.为什么我们需要线程...我可以在线程中执行业务逻辑.我可以在Threads中调用不同的类方法.

java multithreading

12
推荐指数
2
解决办法
2万
查看次数

在一个集合中查找一组数字,在另一个集合中添加一个数字

对于我正在制作的游戏,我有一个我有一个数字列表的情况 - 比如[7,4,9,1,15,2](以此命名A) - 以及另一个数字列表 - 比如[11,18] ,14,8,3](命名B) - 提供给我.我们的目标是找到所有数字组合A,加上一个数字B.例如:

  • 1 + 2 = 3
  • 1 + 7 = 8
  • 2 + 9 = 11
  • 4 + 7 = 11
  • 1 + 2 + 4 + 7 = 14
  • 1 + 2 + 15 = 18
  • 2 + 7 + 9 = 18

...等等.(出于此目的,与之1 + 2相同2 + 1.)

对于像这样的小型列表,对组合进行暴力破坏是微不足道的,但是我面临着看到数千到数万这些数字的可能性,并将在应用程序的生命周期内重复使用这个例程.有没有任何一种优雅的算法可以在100%覆盖率的合理时间内完成此任务?如果不这样,我能找到任何一种体面的启发式方法,可以在合理的时间内给我一套"足够好"的组合吗?

我正在寻找伪代码或任何体面流行和可读语言的算法(注意"和"那里......;)甚至只是英文描述如何实现这种搜索.


编辑添加:

到目前为止提供了大量有用的信息.谢了,兄弟们!总结一下:

  • 问题是NP-Complete,所以没有任何方法可以在合理的时间内获得100%的准确度.
  • 该问题可以视为子集和背包问题的变体.两者都有众所周知的启发式方法,可以适应这个问题. …

algorithm combinations heuristics set np-complete

10
推荐指数
1
解决办法
1405
查看次数

在MIPS64中加载地址

这可能是一个简单明了的事情,我只是没有看到,但如何在MIPS64处理器中加载地址?在MIPS32处理器中,以下汇编程序伪指令:

la $at, LabelAddr
Run Code Online (Sandbox Code Playgroud)

扩展到:

lui $at, LabelAddr[31:16]
ori $at,$at, LabelAddr[15:0]
Run Code Online (Sandbox Code Playgroud)

看一下MIPS64指令集,我看到lui仍然会在32位字的上半部分加载一个16位立即数.似乎没有任何类型的扩展指令将立即加载到64位字的上部区域.那么,似乎要做一个la伪指令的等价物,我需要扩展到代码中,例如:

lui $at, LabelAddr[63:48]
ori $at, $at, LabelAddr[47:32]
sll $at, 16
ori $at, $at, LabelAddr[31:16]
sll $at, 16
ori $at, $at, LabelAddr[15:0]
Run Code Online (Sandbox Code Playgroud)

这让我觉得有点......因为加载一个地址这样基本的东西令人费解,所以它让我确信我忽略了一些东西.

我忽略了什么(如果有的话)?

mips mips64

7
推荐指数
1
解决办法
2331
查看次数