以下是基于我的猜测。有人请指出我理解错误的部分。
如果我有一个类,其中一个实例占用 128 位,称为Class128Bits. 我的程序在 64 位计算机上运行。
首先,我调用let pointer = UnsafeMutablePointer<Calss128Bits>.allocate(capacity: 2)
内存布局应该是这样的:
000-063 064 bits chaos
064-127 064 bits chaos
128-255 128 bits chaos
256-383 128 bits chaos
Run Code Online (Sandbox Code Playgroud)
如果我调用pointer.pointee = aClass128Bits,它会崩溃,因为前两个网格中的指针尚未初始化。访问他们指向的内容会导致不可预测的结果。
但是如果我调用pointer.initialize(to: aClass128Bits, count: 2),指针可以像这样初始化:
000-063 address to offset 128
064-127 address to offset 256
128-255 a copy of aClass128Bits
256-383 a copy of aClass128Bits
Run Code Online (Sandbox Code Playgroud)
那么任何访问都是安全的。然而,这不能解释为什么UnsafeMutablePointer<Int>不崩溃。
指向的指针Int工作正常,但指向String崩溃的指针。我知道我需要像这样初始化它:

但是我看不出我需要通过"42"两次的原因。在 C 中,我可能会做类似这样的事情:
char *pointer …Run Code Online (Sandbox Code Playgroud) 这个问题还有一个额外的限制,那就是IO尽可能避免。
这个限制最初是放在我的问题的最后,似乎很难被注意到。
我实际上知道如何在 Haskell 中实现我的目标,就像我知道如何在其他命令式编程语言中实现它一样 - 命令式方式。
但我没有使用任何其他命令式编程,对吗?我正在使用哈斯克尔。我想要一种 Haskell 方式,一种纯粹的方式。
我通过将额外限制重新定位在相对显眼的位置来重新组织我的问题。那是我的错。非常感谢这些快速回复。
main :: IO ()
main =
putStrLn =<< cachedOrFetched
<$> getLine
<*> getLine
cachedOrFetched :: String -> String -> String
cachedOrFetched cached fetched =
if not $ null cached
then cached
else fetched
Run Code Online (Sandbox Code Playgroud)
上面的代码执行了两次IO。但期望的行为是当第一个 IO 的结果不为 null 时跳过第二个 IO。
我知道我可以通过使用door来实现这一点when。鉴于使用太多dos 违反了我使用 Haskell 的初衷,我可能会接受when.
或者,还有更好的方法?更纯粹的方式?
大约两周前我开始学习 Haskell。我并不期待从中找到工作,只是被编程语言本身所吸引。因为据我所知这是“最纯粹的”。
起初,一切似乎都如我预期的那样好。但后来我发现我必须IO在我的纯代码中写 s 。我花了很长时间才找到一种控制不纯污染的方法。应用函子似乎是拯救者。
有了它,我可以将不纯的 IO“柯里化”到我的纯函数中,这样可以节省大量do,<- …