2009-07-15 6 views
12

나는 Haskell에서 호출 한 C 언어로 작성된 함수가있다. 이 함수는 IO (CInt)을 반환합니다. 때로는 어떤 함수가 반환되는지에 관계없이 모든 함수를 실행하려는 경우가 있습니다. 예제 코드의 위해,이 현재 무슨 일이 일어나고 있는지의 일반적인 생각이다 :하스켈 : 모나드 테이크?

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

내가 원하는 부작용을 얻을, 나는 결과에 대해 걱정하지 않는다. 하지만 이제 원하는 결과를 반환하지 않는 첫 번째 항목이 실행 된 직후에 실행을 중지해야합니다. - 4 이상의 반환 값이 중지 실행을 필요로의 말을하자 그럼 내가 할 원하는 어떤 것은 이것이다 :

 
<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])

그리고 그에게 의미가 : 날이 오류를 제공

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

나 - 결과는 IO 모나드에 여전히 포함되어 있으며 IO 모나드에 포함 된 두 값을 비교할 수는 없습니다. 이것이 정확하게 모나드의 목적이라는 것을 알고 있습니다. 특정 조건이 충족 될 때 결과를 함께 묶어 버리고 연산을 버리는 것입니다.하지만이 경우 모나드 모나드를 "마무리"하여 조건에 따라 체인 실행을 중단하는 쉬운 방법이 있습니다. 내 선택, MonadPlus의 인스턴스를 작성하지 않고?

takeWhile의 목적으로 f의 값만 "언 리프트"할 수 있습니까?

펑터가 적합한 솔루션입니까? 펑 터는 아직 나에게 "클릭"하지 않았지만, 나는 이것을 사용하는 것이 좋은 상황이라고 생각한다.


업데이트 :

@sth 내가 원하는 것과 가장 가까운 답이있다 - 사실, 즉 거의 정확하게 I가 무슨 일이 있었는지,하지만 여전히 가 있는지보고 싶습니다를 표준 명시 적으로 재귀 적이 아닌 솔루션 - 결국 하스켈입니다! 내 질문에 어떻게 대답했는지 되돌아 보면, 이제는 내가 원하는 행동에 대해 충분히 명확하지 않다는 것을 알 수 있습니다.

예를 들어 위에 사용 된 f 기능은 단지 예일뿐입니다. 실제 함수는 C로 작성되고 부작용을 위해 독점적으로 사용됩니다. @mapM_ f (takeWhile (<4) [0..5])의 @ Tom 제안은 사용할 수 없습니다. 입력이 실제로 실행될 때까지 성공할 것인지 실패 할 것인지 전혀 알지 못하기 때문입니다.

반환 된 목록에 대해 실제로 신경 쓰지는 않습니다. 목록이 고갈되거나 첫 번째 C 함수가 실패 코드를 반환 할 때까지 C 함수를 호출하려고합니다.

C 스타일의 의사에, 내 행동은 다음과 같습니다 (?한다)

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

그래서 다시, @의 STH의 대답은 결과가 폐기 될 수 있다는 것을 제외하고, 내가 원하는 정확한 동작을 수행합니다. dropWhileM_ 기능은 나의 목적과 동등합니다. 왜 그런 기능이 없으며 Control.Monad에 takeWhileM_이 있습니까? a similar discussion on a mailing list이 있다는 것을 알았지 만 그 어떤 것도 나오지 않은 것 같습니다.

+0

'sortBy'가'sortByM :: Monad m => (a -> a -> m ordering) -> [a] -> m [a]'의 관점에서 정의되지 않았다는 사실 또한 실망 스럽습니다. –

답변