El mejor enfoque depende del formato del archivo binario.
Muchos formatos binarios están diseñados para facilitar el análisis (a diferencia de los formatos de texto que deben ser leídos principalmente por humanos). Por lo tanto, cualquier tipo de datos de unión estará precedido por un discriminador que le indique qué tipo esperar, todos los campos son de longitud fija o precedidos por un campo de longitud, y así sucesivamente. Para este tipo de datos recomendaría Data.Binary; Por lo general, crea un tipo de datos Haskell coincidente para cada tipo en el archivo y luego convierte a cada uno de esos tipos en una instancia de Binary. Definir el método "get" para leer; devuelve una acción de mónada "Obtener" que es básicamente un analizador muy simple. También necesitarás definir un método "put".
Por otro lado, si sus datos binarios no encajan en este tipo de mundo, entonces necesitará attoparsec. Nunca he usado eso, así que no puedo comentar más, pero this blog post es muy positivo.
Ese Parsec está en Text.Parsec implica que es principalmente para texto, no binario, ¿verdad? Incluso para ByteStrings, solo hace que el tipo sea una instancia de Stream y Char. ¿Qué quieres decir con que funciona bien? – me2