在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?
答案 0 :(得分:8)
如果foo_create
返回的值只取决于x
和name
的值,那么是IO
以外的良好返回值。正如你所说,在Haskell中创建新值会导致分配,并且它们不需要在IO
中,因为不可能观察到在IO
之外分配的特定内存地址,也不可能在IO
之外观察分配是否成功(即程序是否内存不足)。
但是,你说“它是否成功也取决于现实世界”。在这种情况下,不,这是一个有效的操作,应该在IO
中有一个返回类型。类型为makeFoo :: CInt -> CString -> Maybe Foo
的Haskell函数表示Maybe Foo
是Nothing
还是Just _
必须仅依赖于 {{1}的值}和CInt
。这与CString
中的值仅取决于参数一样重要。
如果可以使用相同的参数调用函数并根据现实世界的状态获得不同的结果,那么它根本不是函数,应该是Just
动作。