Я не думаю, что вы найдете какое-либо решение без FFI, которое значительно превосходит либо:
almostForever $ Data.ByteString.hGetSome h1 nr >>= Data.ByteString.hPutStr h2
Или, возможно, вы немного выиграете, используя ленивые байтовые строки:
Data.ByteString.Lazy.hGetContents h1 >>= Data.ByteString.Lazy.hPut h2
Если у вас есть время, запустите их.Если у вас нет времени, просто сделайте это и не беспокойтесь о производительности, если только это не является проблемой.