Haskell의 카레와 포인트 프리 스타일에 대한 혼란
문제
나는 기능을 구현하려고했다
every :: (a -> IO Bool) -> [a] -> IO Bool
그것이 주제였습니다 이 질문. 나는 이것을하려고 노력했다 명백한 재귀없이. 다음 코드를 생각해 냈습니다
every f xs = liftM (all id) $ sequence $ map f xs
내 기능은 게으르지 않았기 때문에 작동하지 않았으므로 (질문에 필요 했음), 거기에 upvotes가 없습니다 :-).
그러나 나는 거기서 멈추지 않았다. 나는 기능을 만들려고 노력했다 포인트 프리 그래서 더 짧아지고 (아마도 더 시원 할 수도 있습니다). 논쟁 이후 f
그리고 xs
내가 방금 떨어 뜨린 표현의 마지막 것입니다.
every = liftM (all id) $ sequence $ map
그러나 이것은 예상대로 작동하지 않았으며 실제로 전혀 효과가 없었습니다.
[1 of 1] Compiling Main ( stk.hs, interpreted ) stk.hs:53:42: Couldn't match expected type `[m a]' against inferred type `(a1 -> b) -> [a1] -> [b]' In the second argument of `($)', namely `map' In the second argument of `($)', namely `sequence $ map' In the expression: liftM (all id) $ sequence $ map Failed, modules loaded: none.
왜 그런 겁니까? 나는 단순히 후행 기능 주장을 단순히 떨어 뜨릴 수 있다는 인상을 받았습니다.
해결책
$의 정의는입니다
f $ x = f x
기능을 완전히 괄호로 만들어 봅시다.
every f xs = (liftM (all id)) (sequence ((map f) xs))
그리고 당신의 카레 버전 :
every = (liftM (all id)) (sequence map)
알다시피, 이것들은 동일하지 않습니다. 후행 기능 인수가 마지막으로 적용된 경우에만 삭제할 수 있습니다. 예를 들어,
f x = g c x
실제로입니다
f x = (g c) x
그리고 X에 (gc)를 적용하는 것은 마지막으로 나옵니다.
f = g c
응용 프로그램 연산자 $의 패턴은 종종 구성 연산자가된다는 것입니다. 포인트가없는 버전. 이 때문입니다
f $ g $ x
동일합니다
(f . g) $ x
예를 들어,
every f xs = liftM (all id) $ sequence $ map f xs
될 수 있습니다
every f xs = (liftM (all id) . sequence . map f) xs
그 시점에서 xs를 떨어 뜨릴 수 있습니다.
every f = liftM (all id) . sequence . map f
인수 f를 제거하는 것은 구성 연산자 앞에 적용되기 때문에 더 어렵습니다. DOT의 정의를 사용해 봅시다 http://www.haskell.org/haskellwiki/pointfree:
dot = ((.) . (.))
포인트가 있습니다
(f `dot` g) x = f . g x
그리고 정확히 모든 포인트를 무료로 만들기 위해 필요한 것입니다.
every = (liftM (all id) . sequence) `dot` map
안타깝게도 Haskell 유형 시스템의 제한으로 인해 명시 적 유형 서명이 필요합니다.
every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool