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

时间:2015-03-18 08:23:13

标签: haskell allocation ffi

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

考虑以下功能:

/**
 * 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?

1 个答案:

答案 0 :(得分:8)

如果foo_create返回的值只取决于xname的值,那么是IO以外的良好返回值。正如你所说,在Haskell中创建新值会导致分配,并且它们不需要在IO中,因为不可能观察到在IO之外分配的特定内存地址,也不可能在IO之外观察分配是否成功(即程序是否内存不足)。

但是,你说“它是否成功也取决于现实世界”。在这种情况下,不,这是一个有效的操作,应该在IO中有一个返回类型。类型为makeFoo :: CInt -> CString -> Maybe Foo的Haskell函数表示Maybe FooNothing还是Just _必须仅依赖于 {{1}的值}和CInt。这与CString中的值仅取决于参数一样重要。

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