导入分配的外部函数时是否需要使用 IO?

Is it necessary to use IO when importing a foreign function that allocates?

在Haskell中,当使用FFI绑定到分配的函数时, 在外部函数分配时 避免 使用 IO 是否合适 for and 构造一些值,而该值 only 取决于函数参数?

考虑以下函数:

/**
 * The foo_create contract: if allocation succeeds, the
 * return value points to a value that depends only on 'x'
 * and 'name', otherwise a null pointer is returned.
 */
foo_t *foo_create(int x, const char *name);

按以下方式导入此功能是否合适?

newtype Foo = Foo (Ptr Foo)

foreign import unsafe "foo.h foo_create"
foo_create :: CInt -> CString -> Ptr Foo

然后可以包装此低级绑定函数以提供 更好的 API:

makeFoo :: CInt -> CString -> Maybe Foo
makeFoo x s =
  let
    ptr = foo_create x s
  in
    if ptr == nullPtr
      then Nothing
      else Just (Foo ptr)

虽然分配会影响现实世界,成功与否也取决于现实世界,但类型确实对 可能的结果。此外,即使是纯函数和数据也可能导致 要分配的 Haskell 运行时。那么,合理吗 在这些情况下避免 IO monad?

如果 foo_create return 的值仅取决于 xname 的值,那么可以 return 值在 [= 之外13=]。正如您所说,在 Haskell 中创建新值会导致分配,并且它们不需要在 IO 中,因为不可能观察到在 IO 之外分配的特定内存地址,并且也无法在 IO.

之外观察 分配是否成功 (即程序是否 运行 内存不足)

然而,你说"whether or not it succeeds is also dependent on the real world"。在那种情况下,不,它是一个有效的操作,它应该在 IO 中有一个 return 类型。类型为 makeFoo :: CInt -> CString -> Maybe Foo 的 Haskell 函数表示 Maybe FooNothing 还是 Just _ 必须取决于 only CIntCString 的值。这与 Just 中的值仅取决于参数一样重要。

如果可以根据现实世界的状态用相同的参数调用一个函数并得到不同的结果,那么它根本就不是一个函数,应该是一个 IO 动作。