2015-03-18 27 views
5

W Haskell, przy korzystaniu z FFI do wiązania się z funkcji, która przydziela, jest to stosowne unikać użyciu IO gdy funkcja zagranicznych przydziela dla i konstruuje pewną wartość, a wartość tylko zależy od argumentów funkcji ?Czy konieczne jest użycie operacji we/wy podczas importowania obcej funkcji, która przydziela?

Rozważmy następującą funkcję:

/** 
* 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); 

byłoby właściwe, aby zaimportować tę funkcję w następujący sposób? Funkcja wiązania

newtype Foo = Foo (Ptr Foo) 

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

Ten niski poziom może być owinięty w celu zapewnienia ładniejszy 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) 

Chociaż przydział wpływa realnym świecie, czy uda się również od w realnym świecie, model ten umożliwia uzyskanie możliwych rezultatów. Co więcej, nawet czyste funkcje i dane mogą powodować przydzielanie środowiska wykonawczego Haskell. Czy jest zatem rozsądne, aby uniknąć monady w takich sytuacjach?

Odpowiedz

8

Jeśli zwraca wartość, która zależy tylko od wartości x i name, to tak, to jest w porządku, zwracana wartość poza IO. Jak mówisz, tworzenie nowych wartości w Haskell powoduje przydzielanie i nie muszą one być w IO, ponieważ niemożliwe jest obserwowanie określonych adresów pamięci przydzielonych poza IO, a także niemożliwe jest obserwowanie , niezależnie od tego, czy alokacja się powiedzie, czy nie. (tzn. Czy programowi brakuje pamięci) poza numerem IO.

Mówisz jednak, że "niezależnie od tego, czy odniosła sukces, zależy również od świata realnego". W takim przypadku nie, jest to skuteczna operacja, która powinna mieć typ zwrotu w IO. Funkcja Haskella z typem makeFoo :: CInt -> CString -> Maybe Foo mówi, że to, czy Maybe Foo jest lub Just _, zależy od wartości CInt i CString. Jest to równie ważne, jak wartość wewnątrz Just zależy tylko od argumentów.

Jeśli można wywołać funkcję z tymi samymi argumentami i uzyskać różne wyniki w zależności od stanu rzeczywistego świata, to nie jest to wcale funkcja i powinna to być akcja IO.

+0

To ma sens. Wydaje się oczywiste z perspektywy czasu! Twoje zdrowie. – frasertweedale