2014-09-16 17 views
13

Urządzenie zawiera tajemniczą, nieudokumentowaną funkcję fixIO. Its source tylko dodaje do tajemnicy:Co robi fixIO?

fixIO :: (a -> IO a) -> IO a 
fixIO k = do 
    m <- newEmptyMVar 
    ans <- unsafeInterleaveIO (takeMVar m) 
    result <- k ans 
    putMVar m result 
    return result 

Wydaje się to zrobić moralnym odpowiednikiem dereferencing NULL (odczyt z pustym MVar). Rzeczywiście, próbując go:

import System.IO 
main = fixIO $ \x -> putStrLn x >> return x 

wyniki w błąd „gwint zablokowane na czas nieokreślony w MVar operacji”

Wyszukany okazuje się nic zaoszczędzić 15 year old message Simon sam Peyton-Jones, w którym świadczy on powyższą źródło i ma nadzieję, że sprawi, że znaczenie będzie jasne (a jednak jestem).

Czy ktoś może rzucić trochę światła na to? Co robi FixIO i kiedy powinienem go używać?

Odpowiedz

11

fixIO to odpowiednik IO odpowiadający fix.

Prawdopodobnie widziałeś tę definicję ciągu Fibonacciego:

fibs = 1 : 1 : zipWith (+) fibs (tail fibs) 

który ponownie wykorzystuje zmienną fibs ramach definicji fibs zrobić corecursion. Działa, ponieważ wykorzystujemy lenistwo do zdefiniowania każdego elementu, zanim będzie on potrzebny.

Możemy użyć fix zrobić to samo bez konieczności definiowania zmiennej tying the knot dla nas:

fix $ \fibs -> 1 : 1 : zipWith (+) fibs (tail fibs) 

co jest przydatne, jeśli nie przede wszystkim trzeba zachować cały ciąg Fibonacciego, po prostu chcesz znać swoje dziesiąte element:

λ (fix $ \fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)) !! 9 
55 

fixIO jest podobna, oprócz tego, że pozwala na przeszukanie na wyjściu działania IO. Właśnie dlatego masz błąd "zablokowany przez wątek" - używałeś wyniku corecursive bez definiowania go.

λ fmap (take 10) . fixIO $ \fibs -> putStrLn "computing fibs" >> return (1 : 1 : zipWith (+) fibs (tail fibs)) 
computing fibs 
[1,1,2,3,5,8,13,21,34,55] 
+0

'fix' nie ma nic wspólnego z brakiem zachowania całej sekwencji fibonacci. "niech kłamstwa = 1: 1: zip z (+) kłamstwami (kłamstwo ogona) w kłamstwach !! 9 "będzie równie dobrze. –

+0

Tom Ellis: Jestem na moim telefonie, ale uważam, że definicja poprawki to 'fix f = let a = f a in a', więc masz rację, to nie jest konieczne. ale jest to równoważne. – rampion

+0

Może również być bardziej zwięzły: 'fix (1:)' jest krótszy niż 'let x = 1: x in x'. – rampion