기능 응용 프로그램:왜$여기에 사용되는?
문제
얼마 전에,나는 질 질문에 대$, 고 있어 유용한 답변-사실,저는 생각을 이해하는 방법을 사용합니다.
그것은 내가 잘못되었다:(
이 예제에서는 튜토리얼:
instance Monad [] where
xs >>= f = concat . map f $ xs
할 수 없습한 이유 볼$사용되었다;ghci 도움이 되지 않게 하거나,으로도 테스트에 나가는 것을 보여 등가 있는 버전으로 단순히 생략$.할 수 있는 사람이 명확히하니까?
해결책
그만큼 $
정상 기능 응용 프로그램보다 우선 순위가 낮기 때문에 여기서 사용됩니다. 이 코드를 작성하는 또 다른 방법은 다음과 같습니다.
instance Monad [] where
xs >>= f = (concat . map f) xs
여기서 아이디어는 먼저 함수를 구성하는 것입니다.concat . map f
) 그런 다음 인수에 적용합니다 (xs
). 도시 된 바와 같이, 이것은 단순히 첫 번째 부분 주위에 괄호를 넣어서 수행 할 수있다.
생략 $
원래 정의에서는 불가능하므로 유형 오류가 발생합니다. 기능 구성 연산자 (the .
)은 표현식을 효과적으로 전환하는 정상 기능 응용 프로그램보다 우선 순위가 낮습니다.
instance Monad [] where
xs >>= f = concat . (map f xs)
기능 구성 연산자에 대한 두 번째 인수는 전혀 기능이 아니기 때문에 의미가 없습니다. 다음 정의가 의미가 있지만 :
instance Monad [] where
xs >>= f = concat (map f xs)
또한, 이것은 또한 내가 선호하는 정의이기도합니다. 왜냐하면 그것이 훨씬 더 명확한 것처럼 보이기 때문입니다.
다른 팁
IMHO가 왜 사용 된 스타일이 아닌지 설명하고 싶습니다.
instance Monad [] where
xs >>= f = concat (map f xs)
concat . map f
소위 포인트 프리 스타일의 글쓰기의 예입니다. PointFree는 "적용 지점없이"를 의미합니다. 수학에서 표현에서 그것을 기억하십시오 y=f(x)
, 우리는 그렇게 말합니다 f
지점에 적용됩니다 x
. 대부분의 경우 실제로 최종 단계를 수행 할 수 있습니다.
f x = something $ x
~와 함께
f = something
처럼 f = concat . map f
, 그리고 이것은 실제로 Pointfree 스타일입니다. 명확한 것은 논쟁의 여지가 있지만, 포인트 프리 스타일은 다른 관점을 제공하는 다른 관점을 제공하므로 때로는 정확히 필요하지 않은 경우에도 사용됩니다.
편집 : Alasdair의 의견을 마친 후에는 Pointfree로 무의미한 것으로 대체되었으며 몇 가지 예제를 수정했습니다.
이유는$은 여기에 사용되는 doe 유형의 서명(.):
(.) :: (b -> c) -> (a -> c) -> a -> c
여기서 우리는
map f :: [a] -> [[b]]
고
concat :: [[b]] -> [b]
그래서 우리는 끝나
concat . map f :: [a] -> [b]
고의 형식(.) 될 수 있으로 기록
(.) ::([[b]]->[b])->([a]->[[b]])->[a]->[b]
만약 우리가 사용하는 concat . map f xs
, 리는
map f xs :: [[b]]
그래서 사용할 수 없습니다(.).(유형해야 할 것(.) ::(a>b)->a>b