2013-04-25 5 views
2

나는 정렬 할 [(String, [String], IO Int)] 목록이 있습니다. sortBy (\x -> ...) list을 사용하려면 IO를 사용하여 IO Int의 내부 값을 가져와야합니다. 즉, Ordering을 반환 할 수 없으며 함수에만 IO Ordering을 반환 할 수 없습니다. 목록을 정렬 할 수있는 방법이 있습니까?IO Int 값을 기준으로 목록을 정렬하는 방법

+0

비교 함수가 'IO'인 경우, 비교할 때마다 변경할 수 있음을 의미합니다. 재현 적으로 두 요소를 비교할 수 없다면 어떻게 목록을 정렬 할 수 있습니까? –

+0

우리는 여기서 추상적으로 이야기하고 있다고 생각합니다. 파이썬이나 자바, 자바 스크립트 같은 전통적인 언어로 어떻게하고 싶습니까? – ErikR

+1

'IO' 액션을 실행하고'Int'를 얻은 다음 목록을 정렬 할 수없는 이유는 무엇입니까? 리스트의 요소를 비교할 때마다 잠재적으로 다른 Int를 얻고 싶습니까? –

답변

7

각 튜플의 세 번째 요소는 IO Int이므로이 값은 외부 세계에 따라 다릅니다. 따라서 정렬 된 목록의 주문은 외부 세계에 따라 다릅니다. 따라서 IO Int 값으로 정렬되는 [(String, [String], IO Int)]을 만들 수있는 방법이 없습니다.

당신 할이 IO [(String, [String], Int)]의 값을, 그리고 당신에게 Int으로 분류 목록을 얻을 것입니다 다른 IO [(String, [String], Int)]을주고IO 모나드에 sortBy 기능 를 들어 올립니다. 그건 순수한 목록이 아니지만, 임의의 순수한 계산을 수행하기 위해 다른 순수 함수를 IO 모나드에 올릴 수 있습니다. 이 같은

뭔가 할 것 :

import Control.Applicative 
import Data.List 

l :: [(String, [String], IO Int)] 
l = [("Foo", [], return 2), ("Bar", [], return 1)] 

f :: Monad m => (a, b, m c) -> m (a, b, c) 
f (x, y, ioz) = ioz >>= \z -> return (x, y, z) 

sl = sortBy (\(x, y, z) (x', y', z') -> compare z z') <$> mapM f l 

가 분명하지 않을 수도 있기 때문에 나는이 그들이 원래 목록에 나타난 순서대로 IO Int 작업을 실행됩니다, 언급해야한다. 하지만 그들을 정렬하려면 Int 값을 얻기 위해 실행해야하며 일부 순서로 실행해야합니다.

+0

이 모나드 리프팅은 정확히 내가 필요한 것입니다. 감사합니다. – Witiko

+0

@Witiko 일반적으로 어떻게 하스켈에서 프로그램하기 위해 노력하고 있습니다. 모든 계산을 순수한 함수로 작성하십시오. 어느 시점에서 계산은'IO' 값에 달려 있지만, 모든 실제 작업을 최대한 빨리하기 위해 순수 함수를'IO' 모나드로 옮기려고합니다. 즉, 'IO'가 존재하지 않는 것처럼 대부분의 작업을 처리 할 수 ​​있으며, IO 코드를 작성하는 경우에도 다시 구현하지 않고 순수한 함수를 들어서 결과를 연결하면됩니다. 'IO' 버전의 것들. – Ben

관련 문제