在Haskell中,基于Iteratee的I/O似乎非常有吸引力.Iteratees是一种可组合,安全,快速的I/O方式,受功能语言中'fold'又称'reduce'功能的启发.基本上,如果你有一个遍历的想法是将遍历状态封装到一个所谓的"枚举器"中,它调用"iteratee",而"iteratee"又是一个函数,它返回一个值或一个更多数据的请求以及一个继续要调用的枚举器.因此,只有枚举器才知道遍历的状态,而迭代者知道如何处理数据并从中构建值.关于它的好处是迭代可以自动组合,其中一个迭代的输出被馈送到另一个迭代以产生更大的迭代.
那么,有两个问题:
在Liu和Hudak撰写的"用箭头堵塞空间泄漏"一文中,声称这会导致O(n ^ 2)运行时行为(用于计算第n项):
successors n = n : map (+1) (successors n)
Run Code Online (Sandbox Code Playgroud)
虽然这给了我们线性时间:
successors n = let ns = n : map (+1) ns
in ns
Run Code Online (Sandbox Code Playgroud)
.这句话肯定是正确的,因为我可以使用GHCi轻松验证.但是,我似乎无法理解为什么,以及在这种情况下结构共享如何帮助.我甚至试图写出计算第三学期的两个扩展.
这是我尝试的第一个变体:
successors 1 !! 2
(1 : (map (+1) (successors 1))) !! 2
(map (+1) (successors 1)) !! 1
(map (+1) (1 : map (+1) (successors 1))) !! 1
2 : (map (+1) (map (+1) (successors 1))) !! 1
(map (+1) (map (+1) (successors 1))) !! 0
(map (+1) (map (+1) (1 : …Run Code Online (Sandbox Code Playgroud) 我正在试验导管包.我还找到了network-conduit包,我试着建立一个简单的TCP客户端,它将文件的内容发送到套接字:
import Data.Conduit
import Data.Conduit.Binary
import Data.Conduit.Network
import Data.ByteString.Char8 (pack)
sendFile fileName appData = runResourceT $
sourceFile fileName $$ appSink appData
main = runTCPClient (clientSettings 8000 (pack "localhost")) (sendFile "book.tex")
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,因为app sink不属于ResourceT:
[1 of 1] Compiling Main ( Conduit2.hs, interpreted )
Conduit2.hs:9:63:
Occurs check: cannot construct the infinite type: m0 = ResourceT m0
Expected type: Application (ResourceT m0)
Actual type: AppData (ResourceT m0) -> m0 ()
In the return type of a call of `sendFile'
In the second argument of …Run Code Online (Sandbox Code Playgroud) 考虑一下我用来解决欧拉问题58的代码:
diagNums = go skips 2
where go (s:skips) x = let x' = x+s
in x':go skips (x'+1)
squareDiagDeltas = go diagNums
where go xs = let (h,r) = splitAt 4 xs
in h:go r
Run Code Online (Sandbox Code Playgroud)
我不喜欢第二个函数中的模式匹配.它看起来比必要的复杂!这对我来说经常出现.在这里,splitAt返回一个元组,所以我必须先解构它才能递归.当我的递归本身返回我想要修改的元组时,相同的模式可能更令人讨厌.考虑:
f n = go [1..n]
where go [] = (0,0)
go (x:xs) = let (y,z) = go xs
in (y+x, z-x)
Run Code Online (Sandbox Code Playgroud)
与简单的递归相比:
f n = go [1..n]
where go [] = 0
go (x:xs) = x+go xs
Run Code Online (Sandbox Code Playgroud)
当然,这里的功能纯属无意义,可以用完全不同的更好的方式编写.但我的观点是,每次我需要通过递归回调多个值时,就会出现模式匹配的需要.
有没有办法避免这种情况,可能是通过使用Applicative或类似的东西?或者你会认为这种风格是惯用的吗?
作为一个相对的Java菜鸟,我很困惑,找出以下内容:
Point.java:
public class Point {
...
public boolean equals(Point other) {
return x == other.x && y == other.y;
}
...
}
Run Code Online (Sandbox Code Playgroud)
Edge.java:
public class Edge {
public final Point a, b;
...
public boolean equals(Edge other) {
return a.equals(other.a) && b.equals(other.b);
}
...
}
Run Code Online (Sandbox Code Playgroud)
main snippet:private Set blockedEdges;
public Program(...) {
...
blockedEdges = new HashSet<Edge>();
for (int i = 0; ...) {
for (int j = 0; ...) {
Point p = new Point(i, j);
for (Point …Run Code Online (Sandbox Code Playgroud)