haskus / packages

Haskus packages
https://haskus.org/
24 stars 11 forks source link

Unsoundness issues when using `forM` with `throwE` in `Excepts` #39

Closed hasufell closed 2 years ago

hasufell commented 2 years ago

Minimal repro here: https://github.com/hasufell/excepts-bug

More specifically, the following code:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}

module Main where

import Control.Monad
import Control.Monad.IO.Class
import Haskus.Utils.Variant.Excepts

data MyError = MyError String

main :: IO ()
main = do
  e1 <- runE ex1
  putStrLn $ show e1
  e2 <- runE ex2
  putStrLn $ show e2

 where
  ex1 :: MonadIO m => Excepts '[MyError] m ()
  ex1 = void $ forM [1, 2] $ \i -> do
              liftIO $ putStrLn $ show i
              throwE (MyError $ show i)

  ex2 :: MonadIO m => Excepts '[MyError] m ()
  ex2 = forM_ [1, 2] $ \i -> do
              liftIO $ putStrLn $ show i
              throwE (MyError $ show i)

will print

1
2
VLeft MyError "1"
1
VLeft MyError "1"

This was discovered in ghcup, where an error doesn't short-circuit the computation.

hasufell commented 2 years ago

@hsyl20

hsyl20 commented 2 years ago

Thanks for the report and the PR! I've just released 3.2.1 on Hackage