your programing

Haskell의 도트 연산자 : 더 많은 설명이 필요합니다.

lovepro 2020. 10. 11. 11:07
반응형

Haskell의 도트 연산자 : 더 많은 설명이 필요합니다.


이 Haskell 코드에서 도트 연산자가 수행하는 작업을 이해하려고합니다.

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

예제의 스타일은 "점없는"스타일이라고하며 함수에 대한 인수는 생략됩니다. 이것은 많은 경우에 더 명확한 코드를 만듭니다. (처음 보는 것은 어렵지만 잠시 후에 익숙해 질 것입니다. 일반적인 Haskell 관용구입니다.)

여전히 혼란 스러우면 .UNIX 파이프와 같은 것과 관련 하여 도움이 될 수 있습니다 . 경우 f의 출력이되고 g출력이됩니다의 입력 ' h의 입력을, 당신은 같은 명령 행에 그 쓰기 것 f < x | g | h. Haskell에서는 .UNIX처럼 작동 |하지만 "뒤로"- h . g . f $ x. 이 표기법은 예를 들어 목록을 처리 할 때 매우 유용합니다. 과 같은 다루기 힘든 구조 대신 map (\x -> x * 2 + 10) [1..10]그냥 쓸 수 있습니다 (+10) . (*2) <$> [1..10]. (그리고 해당 함수를 단일 값에만 적용하려면 (+10) . (*2) $ 10. Consistent입니다!)

Haskell 위키에는 좀 더 자세한 내용이 담긴 좋은 기사가 있습니다 : http://www.haskell.org/haskellwiki/Pointfree


. 연산자는 함수를 구성합니다. 예를 들면

a . b

어디 b를 함수는 새로운되어있는 기능 이 다음 인수, b를 실행하는 결과에. 귀하의 코드

sumEuler = sum . (map euler) . mkList

다음과 정확히 동일합니다.

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

하지만 읽기가 더 쉬울 것입니다. map euler 주위에 괄호가있는 이유는 sum , map eulermkList - map euler 가 단일 함수 라는 세 가지 함수가 구성되어 있음을 더 명확하게하기 때문 입니다.


sum에 대한 인수가 아니라 Haskell Prelude의 함수입니다 sumEuler. 유형이 있습니다

Num a => [a] -> a

함수 구성 연산자 .에는 유형이 있습니다.

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

그래서 우리는

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

참고 Int참의 인스턴스입니다 Numtypeclass.


. 연산자는 함수 구성에 사용됩니다. 수학과 마찬가지로 f (x) 및 g (x) f 함수가 필요한 경우. g는 f (g (x))가됩니다.

map은 목록에 함수를 적용하는 내장 함수입니다. 함수를 괄호 안에 넣으면 함수가 인수로 처리됩니다. 이것에 대한 용어는 카레 입니다. 당신은 그것을 찾아야합니다.

하는 것은 두 개의 인수를 갖는 함수를 취하고 인수 오일러를 적용한다는 것입니다. (맵 오일러) 맞죠? 결과는 하나의 인수 만 취하는 새 함수입니다.

합계. (지도 오일러). mkList는 기본적으로이 모든 것을 합치는 멋진 방법입니다. 내 Haskell은 약간 녹슬었지만 마지막 기능을 직접 조합 할 수 있습니까?


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


Haskell의 점 연산자

이 Haskell 코드에서 도트 연산자가 수행하는 작업을 이해하려고합니다.

sumEuler = sum . (map euler) . mkList

짧은 답변

점이없는 등가 코드, 즉

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

또는 람다없이

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

점 (.)은 기능 구성을 나타냅니다.

더 긴 답변

먼저 eulerto 의 부분적 적용을 단순화합시다 map.

map_euler = map euler
sumEuler = sum . map_euler . mkList

이제 우리는 점만 가지고 있습니다. 이 점은 무엇을 표시합니까?

에서 소스 :

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

Thus (.) is the compose operator.

Compose

In math, we might write the composition of functions, f(x) and g(x), that is, f(g(x)), as

(f ∘ g)(x)

which can be read "f composed with g".

So in Haskell, f ∘ g, or f composed with g, can be written:

f . g

Composition is associative, which means that f(g(h(x))), written with the composition operator, can leave out the parentheses without any ambiguity.

That is, since (f ∘ g) ∘ h is equivalent to f ∘ (g ∘ h), we can simply write f ∘ g ∘ h.

Circling back

Circling back to our earlier simplification, this:

sumEuler = sum . map_euler . mkList

just means that sumEuler is an unapplied composition of those functions:

sumEuler = \x -> sum (map_euler (mkList x))

참고URL : https://stackoverflow.com/questions/631284/dot-operator-in-haskell-need-more-explanation

반응형