Haskell: monadic takeWhile?

Eu tenho algumas funções escritas em C que eu chamo de Haskell. Essas funções retornamIO (CInt). Às vezes, quero executar todas as funções, independentemente do que elas retornam, e isso é fácil. Para fins de código de exemplo, esta é a ideia geral do que está acontecendo atualmente:

Prelude> let f x = print x >> return x
Prelude> mapM_ f [0..5]
0
1
2
3
4
5
Prelude>

Eu obtenho meus efeitos colaterais desejados e não me importo com os resultados. Mas agora eu preciso parar a execução imediatamente após o primeiro item que não retorna o resultado desejado. Digamos que um valor de retorno de 4 ou superior exija que a execução pare - então o que euquer fazer é isto:

Prelude> takeWhile (<4) $ mapM f [0..5]

O que me dá esse erro:

<interactive>:1:22:
    Couldn't match expected type `[b]' against inferred type `IO a'
    In the first argument of `mapM', namely `f'
    In the second argument of `($)', namely `mapM f ([0 .. 5])'
    In the expression: takeWhile (< 4) $ mapM f ([0 .. 5])

E isso faz sentido para mim - o resultado ainda está contido na IO mônada, e não posso simplesmente comparar dois valores contidos na IO mônada. Eu sei que este é precisamente o propósito das mônadas - encadeando os resultados juntos e descartando as operações quando uma certa condição é satisfeita - mas existe uma maneira fácil de "encerrar" a môn IO neste caso para parar de executar a cadeia sob uma condição? de minha escolha, sem escrever um exemplo deMonadPlus?

Posso apenas "desligar" os valores def, para os fins do takeWhile?

Esta é uma solução onde os functores se encaixam? Os instrutores ainda não "clicaram" comigo, mas meio que tenho a impressão de que essa pode ser uma boa situação para usá-los.

Atualizar:

@sth tem a resposta mais próxima para o que eu quero - na verdade, isso é quase exatamente o que eu estava procurando, mas eu ainda gostaria de ver se existepadrão solução que não é explicitamente recursiva - afinal, é o Haskell! Olhando para trás, como eu redigi minha pergunta, agora posso ver que não estava claro o suficiente sobre o meu comportamento desejado.

of A função que usei acima para um exemplo foi meramente um exemplo. As funções reais são escritas em C e usadas exclusivamente para seus efeitos colaterais. Eu não posso usar a sugestão de @ Tom demapM_ f (takeWhile (<4) [0..5]) porque não tenho idéia se alguma entrada realmente resultará em sucesso ou falha até ser executada.

Eu realmente não me importo com a lista retornada - eu só quero chamar as funções C até que a lista esteja esgotada ou a primeira função C retorne um código de falha.

No pseudocódigo do estilo C, meu comportamento seria:

do {
    result = function_with_side_effects(input_list[index++]);
} while (result == success && index < max_index);

Então, novamente, a resposta do @ sth realiza o comportamento exato que eu quero, exceto que os resultados podem (devem?) Ser descartados. UMAdropWhileM_ função seria equivalente para os meus propósitos. Por que não há uma função como essa outakeWhileM_ em Control.Monad? Vejo que houveuma discussão semelhante em uma lista de discussão, mas parece que nada veio disso.

questionAnswers(5)

yourAnswerToTheQuestion