Неужели Haskell выбрасывает искру, когда трюк собирает мусор?

Например:

x :: Maybe a
y :: a
y `par` x `pseq` (fromMaybe y x)

Является ли искра y остановлена ​​и отбрасывается, если x вычисляется (намного) раньше и составляет Just ...?

Чтобы быть более конкретным, я хочу искать список, но каждое сравнение довольно дорого. Я хотел бы распараллелить поиск, но мне хотелось бы, чтобы остальные сравнения были отброшены после обнаружения совпадения.

Ответы

Ответ 1

Вы имели в виду fromMaybe вместо maybe?

x `par` y `pseq` (fromMaybe y x)

Также вы создаете искру для оценки x, а не y. Поэтому fromMaybe y x не будет оцениваться до тех пор, пока не будет оценен y. Возможно, вы имели в виду обратное:

y `par` x `pseq` (fromMaybe y x)

Если все вышеизложенное верно, тогда ответ на ваш вопрос "нет", искра не будет остановлена, когда она уже запущена (хотя она будет отброшена, если она еще не началась). Вы можете проверить ее с помощью следующего теста:

import Data.Maybe
import Control.Concurrent
import Control.Parallel
import System.IO.Unsafe
import System.Mem

{-# NOINLINE x #-}
x = unsafePerformIO $ do
  threadDelay 1000
  return (Just 1)

{-# NOINLINE y #-}
y = unsafePerformIO $ do
  print "will eval y"
  threadDelay 3000000
  print "did eval y"
  return (2 :: Int)

main :: IO ()
main = do
  print $ y `par` x `pseq` fromMaybe y x
  print "done"
  performGC
  threadDelay 4000000

Выход:

"will eval y"
1
"done"
"did eval y"

Также вы можете проверить статистику времени выполнения, +RTS -s. Он содержит несколько искр GC'd.