문제

이 Haskell 코드에서 DOT 운영자가 무엇을하고 있는지 이해하려고합니다.

sumEuler = sum . (map euler) . mkList

전체 소스 코드는 다음과 같습니다.

내 이해

도트 연산자는 두 기능을 수행하고 있습니다 sum 그리고 결과 map euler 그리고 결과 mkList 입력으로.

하지만, sum 함수가 함수의 인수가 아닌가? 그래서 여기서 무슨 일이 일어나고 있습니까?

또한, 무엇이 있습니다 (map euler) 행위?

암호

mkList :: Int -> [Int]
mkList n = [1..n-1]

euler :: Int -> Int
euler n = length (filter (relprime n) (mkList n))

sumEuler :: Int -> Int
sumEuler = sum . (map euler) . mkList
도움이 되었습니까?

해결책

간단히 말하다 . 수학과 마찬가지로 기능 구성입니다.

f (g x) = (f . g) x

귀하의 경우 새로운 기능을 만들고 있습니다. sumEuler 다음과 같이 정의 할 수 있습니다.

sumEuler x = sum (map euler (mkList x))

예제의 스타일을 "Point-Free"스타일이라고합니다. 함수에 대한 인수는 생략됩니다. 이것은 많은 경우 더 명확한 코드를 만듭니다. (처음 보는 것은 처음으로 생각하기가 어려울 수 있지만 잠시 후에 익숙해 질 것입니다. 일반적인 Haskell 관용구입니다.)

여전히 혼란스러워하면 관련이있는 데 도움이 될 수 있습니다. . 유닉스 파이프와 같은 것. 만약에 f의 출력이됩니다 g출력이되는 입력 h입력, 당신은 명령 줄에 다음과 같이 씁니다. f < x | g | h. Haskell에서 . 유닉스처럼 작동합니다 |, 그러나 "거꾸로" - h . g . f $ x. 목록을 처리 할 때이 표기법이 매우 도움이된다고 생각합니다. 다루기 힘든 건축 대신 map (\x -> x * 2 + 10) [1..10], 당신은 그냥 쓸 수 있습니다 (+10) . (*2) <$> [1..10]. (그리고 그 기능 만 단일 값으로 적용하려면; (+10) . (*2) $ 10. 일관된!)

Haskell Wiki는 더 자세한 내용을 가진 좋은 기사를 가지고 있습니다. http://www.haskell.org/haskellwiki/pointfree

다른 팁

. 연산자는 기능을 작성합니다. 예를 들어,

a . b

어디에 그리고 기능은 새로운 것입니다 기능 그것은 논쟁에서 B를 실행하고, 그 결과는 그 결과에 대해서도 실행됩니다. 코드

sumEuler = sum . (map euler) . mkList

정확히 동일합니다.

sumEuler myArgument = sum (map euler (mkList myArgument))

그러나 읽기가 더 쉽습니다. 주위에 파렌이있는 이유 맵 오일러 3 가지 기능이 구성되어 있음을 더 명확하게하기 때문입니다. 합집합, 맵 오일러 그리고 mklist - 맵 오일러 단일 함수입니다.

sum Haskell Prelude의 함수는 다음과 같은 주장이 아닙니다. sumEuler. 유형이 있습니다

Num a => [a] -> a

기능 구성 연산자 . 유형이 있습니다

(b -> c) -> (a -> b) -> a -> c

그래서 우리는 가지고 있습니다

sum                        :: Num a => [a] -> a
map                        :: (a -> b) -> [a] -> [b]
euler                      :: Int -> Int
mkList                     :: Int -> [Int]
(map euler)                :: [Int] -> [Int]
(map euler) . mkList       :: Int -> [Int]
sum . (map euler) . mkList :: Int -> Int

주목하십시오 Int 인스턴스입니다 Num.

. 연산자는 기능 구성에 사용됩니다. 수학과 마찬가지로 F (x) 및 g (x) f를 함수 해야하는 경우. g는 f (g (x))가된다.

MAP은 기능을 목록에 적용하는 내장 기능입니다. 함수를 괄호 안에 넣음으로써 함수는 인수로 취급됩니다. 이것에 대한 용어입니다 카레. 당신은 그것을 찾아야합니다.

하는 것은 두 가지 인수가있는 함수가 필요하다는 것입니다. 인수 Euler를 적용합니다. (Map Euler) 맞습니까? 그리고 결과는 새로운 기능으로 하나의 주장만을 취합니다.

합계 (지도 오일러). MKList는 기본적으로 모든 것을 정리하는 멋진 방법입니다. 내 haskell은 약간 녹슬었지만 아마도 그 마지막 기능을 스스로 정리할 수 있을까요?

도트 연산자는 왼쪽에 함수를 적용합니다 (sum) 오른쪽에있는 함수의 출력에. 귀하의 경우에는 여러 기능을 함께 정리하고 있습니다. 결과를 전달합니다. mkList 에게 (map euler), 그리고 그 결과를 전달합니다 sum. 이 지역 여러 개념에 대한 좋은 소개가 있습니다.

Haskell의 DOT 운영자

이 Haskell 코드에서 DOT 운영자가 무엇을하고 있는지 이해하려고합니다.

sumEuler = sum . (map euler) . mkList

짧은 대답

점이없는 동등한 코드입니다

sumEuler = \x -> sum ((map euler) (mkList x))

또는 람다없이

sumEuler x = sum ((map euler) (mkList x))

도트 (.)는 함수 구성을 나타 내기 때문입니다.

더 긴 답변

먼저, 부분 적용을 단순화합시다 euler 에게 map:

map_euler = map euler
sumEuler = sum . map_euler . mkList

이제 우리는 단지 점을 가지고 있습니다. 이 점들에 의해 표시되는 것은 무엇입니까?

에서 출처:

(.)    :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)

따라서 (.) 입니다 연산자를 구성하십시오.

구성하다

수학에서, 우리는 기능의 구성, f (x) 및 g (x), 즉 f (g (x))를 작성할 수 있습니다.

(f ∘ g) (x)

"f"를 읽을 수 있습니다.

따라서 Haskell에서는 G로 구성된 F 또는 F를 작성할 수 있습니다.

f . g

조성물은 연관성이며, 이는 구성 연산자와 함께 작성된 F (g (h (x)))가 모호함없이 괄호를 제거 할 수 있음을 의미합니다.

즉, (f since g) ∘ h는 f ∘ (g ∘ h)와 동일하기 때문에 단순히 f ∘ g ∘ h를 쓸 수 있습니다.

뒤로 돌면

초기 단순화로 되돌아 가면 :

sumEuler = sum . map_euler . mkList

단지 그것을 의미합니다 sumEuler 이러한 기능의 적용되지 않은 구성입니다.

sumEuler = \x -> sum (map_euler (mkList x))
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top