Haskell : <*>은 어떻게 발음하나요? [닫은]


109

Applicative typeclass에서 이러한 함수를 어떻게 발음합니까?

(<*>) :: f (a -> b) -> f a -> f b
(*>)  :: f a -> f b -> f b
(<*)  :: f a -> f b -> f a

(즉, 운영자가 아니라면 무엇이라고 부를 수 있습니까?)

참고로, pure수학자가 아닌 사람들에게 더 친숙한 이름 으로 이름 을 바꿀 수 있다면 무엇이라고 부르겠습니까?


6
@J Cooper ... 우리가 어떻게 발음하는지들을 수 있겠습니까? :) 음성 녹음 및 재생 기능에 대한 요청을 meta.stackoverflow.com에 게시 할 수 있습니다. :).
Kiril

8
"좋은 슬픔, 정말 대원이 부족 했죠?"라고 발음됩니다. 또한, 대한 좋은 이름이 pure될 수 있습니다 makeApplicative.
Chuck

@Lirik, 글쎄, 나는 @Chuck, 당신의 게시 : 나는 "이 일을 전화 Whaddya는"말은 발음에 의해 추측 pure에 대한 답변으로 제안을하고 난 당신을 upvote에 있습니다
J 쿠퍼

6
(<*>)는 Control.Monad의 "ap"의 Control.Applicative 버전이므로 "ap"이 아마도 가장 적절한 이름 일 것입니다.
Edward KMETT

11
나는 그것을 사이클롭스라고 부르고 싶지만 그것은 나뿐입니다.
RCIX

답변:


245

죄송합니다. 저는 제 수학을 잘 모릅니다. 그래서 Applicative typeclass에서 함수를 어떻게 발음하는지 궁금합니다.

당신의 수학을 안다는 것은 여기에서 대체로 무관하다고 생각합니다. 아시다시피 Haskell은 추상 수학의 다양한 분야, 특히 범주 이론 에서 몇 가지 용어를 차용합니다 . 여기서 펑터와 모나드를 얻습니다. Haskell에서 이러한 용어의 사용은 공식적인 수학적 정의와 다소 차이가 있지만, 어쨌든 좋은 설명 용어가 될만큼 일반적으로 충분히 가깝습니다.

Applicative형 클래스 사이의 어딘가에 앉아 FunctorMonad하나가 유사한 수학적 근거가 기대 있도록. Control.Applicative모듈 설명서는 다음으로 시작됩니다.

이 모듈은 펑터와 모나드 사이의 중간 구조를 설명합니다. 순수한 표현과 시퀀싱을 제공하지만 바인딩은 제공하지 않습니다. (기술적으로는 강력한 느슨한 모노 이드 펑터입니다.)

흠.

class (Functor f) => StrongLaxMonoidalFunctor f where
    . . .

아니 꽤 인기를 얻기 쉬운으로 Monad, 나는 생각한다.

이 모든 것이 기본적으로 요약되는 Applicative것은 수학적으로 특히 흥미로운 개념과 일치하지 않기 때문에 Haskell에서 사용되는 방식을 포착하는 기성 용어가 주변에 존재하지 않는다는 것입니다. 따라서 지금은 수학을 제쳐두십시오.


우리가 무엇을 부를지 알고 싶다면 (<*>)그것이 기본적으로 무엇을 의미하는지 아는 것이 도움이 될 것입니다.

그래서 함께이야 Applicative어쨌든, 왜 합니까 우리는 그 전화를?

무엇 Applicative실제로 금액은 들어 올릴 수있는 방법은 임의의 에 기능을 Functor. Maybe(가장 단순 Functor하고 사소하지 않은 ) 및 Bool(가장 단순한 사소하지 않은 데이터 유형) 의 조합을 고려하십시오 .

maybeNot :: Maybe Bool -> Maybe Bool
maybeNot = fmap not

이 기능은 fmap우리가 들어 있습니다 not작업에서 Bool작업에 Maybe Bool. 하지만 우리가 들어 올리고 싶다면 (&&)?

maybeAnd' :: Maybe Bool -> Maybe (Bool -> Bool)
maybeAnd' = fmap (&&)

글쎄, 그건 우리가 원하는 게 아니에요 전혀 ! 사실, 그것은 거의 쓸모가 없습니다. 우리는 영리 해 지려고 노력할 수 있고 다른 사람 Bool을 등을 Maybe통해 몰래 들어갈 수 있습니다 ...

maybeAnd'' :: Maybe Bool -> Bool -> Maybe Bool
maybeAnd'' x y = fmap ($ y) (fmap (&&) x)

...하지만 그것은 좋지 않습니다. 한 가지는 잘못된 것입니다. 또 다른 것은 추악 합니다. 우리는 계속해서 시도 할 수 있지만 , 임의의Functor . 성가신!

반면에 MaybeMonad인스턴스를 사용하면 쉽게 할 수 있습니다 .

maybeAnd :: Maybe Bool -> Maybe Bool -> Maybe Bool
maybeAnd x y = do x' <- x
                  y' <- y
                  return (x' && y')

이제는 단순한 함수를 번역하는 데 많은 번거 로움이 있습니다. 그래서 Control.Monad자동으로 수행하는 함수를 제공합니다 liftM2. 이름에서 2는 정확히 두 개의 인수의 함수에서 작동한다는 사실을 나타냅니다. 3, 4 및 5 인수 함수에 대해 유사한 함수가 존재합니다. 이러한 함수는 좋지만 완벽하지는 않으며 인수 수를 지정하는 것은 추하고 서투른 작업입니다.

어느 우리에게 가져다 실용적 타입의 클래스를 도입 종이 . 여기에서 저자는 본질적으로 두 가지 관찰을합니다.

  • 다중 인수 함수를 a Functor로 해제하는 것은 매우 자연스러운 일입니다.
  • 그렇게하기 위해 모든 기능이 필요하지는 않습니다. Monad

일반 함수 응용 프로그램은 용어의 단순한 병치에 의해 작성되므로 "리프트 된 응용 프로그램"을 가능한 한 간단하고 자연스럽게 만들기 위해이Functor 문서에서는 응용 프로그램을위한 중위 연산자를 소개 하고으로 들어 올려 그에 필요한 것을 제공하는 유형 클래스를 소개합니다. .

이 모든 것이 우리에게 다음과 같은 요점을 가져다줍니다. (<*>)단순히 함수 응용을 나타냅니다. 그렇다면 공백 "병치 연산자"를 사용하는 것과 다르게 발음하는 이유는 무엇입니까?

하지만 그다지 만족스럽지 않다면 Control.Monad모듈이 모나드에 대해 동일한 작업을 수행하는 함수도 제공 한다는 것을 알 수 있습니다 .

ap :: (Monad m) => m (a -> b) -> m a -> m b

어디 ap"적용"에 대한 짧은 물론이다. 어떤 때문에 Monad할 수 있습니다 Applicative, 그리고 ap기능은 후자에 제시의 하위 집합 만 필요, 우리는 아마도 말할 수있는 경우 (<*>)운영자하지 않았다, 그것은 호출해야합니다 ap.


다른 방향에서도 접근 할 수 있습니다. Functor리프팅 작업이라고 fmap는 일반화이기 때문에 map목록에 작업이. 목록에서 어떤 종류의 기능이 작동 (<*>)합니까? 이 무슨 ap물론, 목록에 않지만, 그 자체에 특히 유용 아니다.

실제로 목록에 대한보다 자연스러운 해석이있을 수 있습니다. 다음 유형 서명을 보면 무엇이 떠오르나요?

listApply :: [a -> b] -> [a] -> [b]

목록을 병렬로 정렬하여 첫 번째의 각 기능을 두 번째의 해당 요소에 적용하는 아이디어에 대해 너무 유혹적인 것이 있습니다. 우리의 오랜 친구에게는 안타깝게도이Monad 간단한 작업 목록의 길이가 다른 경우 모나드 법칙을 위반합니다 . 그러나 그것은 괜찮 Applicative습니다.이 경우 일반화 된 버전을 함께 묶는(<*>) 방법이됩니다. 그래서 우리는 그것을 호출하는 것을 상상할 수 있습니까?zipWithfzipWith


이 압축 아이디어는 실제로 우리에게 완전한 원을 제공합니다. 이전에 모노 이드 펑터에 대한 수학 내용을 기억하십니까? 이름에서 알 수 있듯이 다음은 익숙한 Haskell 유형 클래스 인 모노 이드와 펑터의 구조를 결합하는 방법입니다.

class Functor f where
    fmap :: (a -> b) -> f a -> f b

class Monoid a where
    mempty :: a
    mappend :: a -> a -> a

상자에 넣어서 약간 흔들면 어떻게 생겼을까 요? 에서 Functor우리는의 생각하겠습니다 그 형식 매개 변수의 구조 무관 하고,에서 Monoid우리가 함수의 전체 형태를 유지하는 것입니다 :

class (Functor f) => MonoidalFunctor f where
    mfEmpty :: f ?
    mfAppend :: f ? -> f ? -> f ?

우리는 진정으로 "빈"을 생성하는 방법이 있다고 가정하고 싶지 Functor않으며 임의의 유형의 값 을 만들 수 없으므로 mfEmptyas 유형을 수정합니다 f ().

또한 mfAppend일관된 유형 매개 변수가 필요 하도록 강요하고 싶지 않으므로 이제 다음과 같이합니다.

class (Functor f) => MonoidalFunctor f where
    mfEmpty :: f ()
    mfAppend :: f a -> f b -> f ?

결과 유형은 mfAppend무엇입니까? 우리는 우리가 전혀 모르는 두 가지 임의의 유형이 있으므로 많은 옵션이 없습니다. 가장 현명한 것은 다음 두 가지를 모두 유지하는 것입니다.

class (Functor f) => MonoidalFunctor f where
    mfEmpty :: f ()
    mfAppend :: f a -> f b -> f (a, b)

어느 시점 에서 목록 mfAppend의 일반화 된 버전이 명확하게 zip표시되며 Applicative쉽게 재구성 할 수 있습니다.

mfPure x = fmap (\() -> x) mfEmpty
mfApply f x = fmap (\(f, x) -> f x) (mfAppend f x)

이것은 또한 pure의 식별 요소와 관련되어 있음을 보여 Monoid주므로 다른 좋은 이름은 단위 값, null 연산 등을 제안하는 모든 것일 수 있습니다.


길이가 길어서 요약하면 다음과 같습니다.

  • (<*>) 단지 수정 된 함수 응용 프로그램이므로 "ap"또는 "apply"로 읽거나 일반 함수 응용 프로그램처럼 완전히 제거 할 수 있습니다.
  • (<*>)또한 대략적 zipWith으로 목록을 일반화 하므로 fmap"map a functor with" 로 읽는 것과 유사하게 "zip functors with"로 읽을 수 있습니다 .

첫 번째는 Applicative이름에서 알 수 있듯이 유형 클래스 의 의도에 더 가깝기 때문에 이것이 제가 권장하는 것입니다.

사실, 저는 해제 된 모든 응용 프로그램 운영자를 자유롭게 사용하고 비 발음을 권장합니다 .

  • (<$>), 단일 인수 함수를 Functor
  • (<*>), 다중 인수 함수를 Applicative
  • (=<<), Monad기존 계산에 a 를 입력하는 함수를 바인딩합니다.

이 세 가지 모두 마음에 규칙적인 기능을 적용하는 것입니다.


6
@Colin Cochrane : "장풍"철자를 잘못 입력하지 않으 셨나요? :)하지만 이봐, 내가 할게! 나는 항상 그것을 느끼고 Applicative그것이 촉진하는 기능적 관용적 스타일이 충분한 사랑을 얻지 못하기 때문에 내가 어떻게 발음하는지 설명하는 수단으로 그 미덕을 약간 칭찬 할 기회를 거부 할 수 없었습니다 (<*>).
CA McCann


6
Haskell에 Applicative's에 대한 구문 설탕이 있었습니까 ? [| f a b c d |](원본에서 제안한대로) 같은 것 . 그런 다음 <*>결합자가 필요하지 않으며 이러한 표현을 "기능적 컨텍스트에서 함수 응용 프로그램"의 예로 참조 할 수 있습니다.
Tom Crockett

1
@FredOverflow : 아니요, Monad. 또는 Functor또는 Monoid3 개 미만의 형용사를 포함하는 잘 정립 된 용어가있는 다른 것. "적용 적"은 비록 합리적으로 설명 적이긴하지만 오히려 영감을주지 않는 이름이 오히려 필요한 것에 박힌 이름입니다.
CA McCann

1
@pelotom : 참조 [ stackoverflow.com/questions/12014524/… 친절한 사람들이 거의 그 표기법을 얻는 두 가지 방법을 보여주었습니다.
AndrewC 2012-08-22

21

CA McCann의 기술적 답변 을 개선하려는 야망이 없기 때문에 좀 더 푹신한 답변을 다룰 것입니다.

pure나 같은 podunk에게 더 친숙한 이름 으로 이름 을 바꿀 수 있다면 무엇이라고 부르겠습니까?

대안으로, 특히 Monad" return" 라는 버전 에 대한 끊임없는 불안과 배신으로 가득 찬 외침에 끝이 없기 때문에 명령형 프로그래머의 가장 명령을 충족시킬 수있는 방식으로 그 기능을 제안하는 다른 이름을 제안합니다. , 그리고 가장 기능적인 ... 글쎄, 바라건대 모든 사람들이 똑같이 불평 할 수 있습니다 inject.

가치를 가져라. 에 "주입"는 Functor, Applicative, Monad, 또는 무엇을 가지고 - 당신은. " inject"에 투표 하고이 메시지를 승인했습니다.


4
나는 보통 "단위"또는 "리프트"와 같은 것에 의지하지만, Haskell에서는 이미 다른 의미가 너무 많습니다. inject은 훌륭한 이름이고 아마도 내 것보다 낫지 만, 부수적으로 "inject"는 일종의 왼쪽 접는 방법으로 Smalltalk와 Ruby에서 사용됩니다. 이름 선택을 이해하지 못했습니다 ...
CA McCann

3
이것은 매우 오래된 스레드이지만 injectRuby & Smalltalk에서는 목록의 각 요소 사이에 연산자를 "주입"하는 것과 같기 때문에 사용 한다고 생각 합니다. 적어도 저는 항상 그렇게 생각했습니다.
조나단 스털링

1
이전 사이드 스레드 를 다시 선택 하려면 연산자를 주입하지 않고 이미있는 생성자를 대체 (제거)합니다. (반대로 보면 이전 데이터를 새 유형에 주입 하는 것입니다.) 목록의 경우 제거는 foldr. (당신은 대체 (:)[](:)이 개 인수를 받아 []일정한이다 따라서, foldr (+) 0 (1:2:3:[])1+2+3+0에.) Bool그것은 단지 if- then- else(두 상수 하나를 선택)와 대한 Maybe이 호출 maybe... 하스켈은 모든 다른 유형을 가지고,이에 대한 하나의 이름 / 기능이 없습니다 (일반 엘림 단지 재귀 / 유도 없음)
아무도

@CAMcCann Smalltalk는 베트남 전쟁 초안에 대한 Arlo Guthrie 노래 에서 이름을 얻었습니다. 불행한 젊은이들이 수집되고, 선택되고, 때로는 거부되고, 그렇지 않으면 주입되었습니다.
Tom Anderson

7

간단히 말해서 :

  • <*>당신은 그것을 적용 이라고 부를 수 있습니다 . 그래서 Maybe f <*> Maybe a로 발음 할 수있다 적용 Maybe f을 통해Maybe a .

  • 많은 JavaScript 라이브러리처럼 이름 pure을로 바꿀 of수 있습니다. JS Maybe에서 Maybe.of(a).

또한 Haskell의 위키에는 언어 연산자의 발음에 대한 페이지가 있습니다.


3
(<*>) -- Tie Fighter
(*>)  -- Right Tie
(<*)  -- Left Tie
pure  -- also called "return"

Source : Haskell Programming from First Principles , by Chris Allen and Julie Moronuki


내가 말할 수있는 한 그 이름은 정확히 포착되지 않았습니다.
dfeuer

@dfeuer는 그 책을 주요 학습 자료로 사용하는 차세대 Haskeller를 기다립니다.
dmvianna

1
일어날 수 있습니다. 그러나 그 이름은 의미와 관련이 없기 때문에 끔찍합니다.
dfeuer

1
@dfeuer, 나는 어디에서나 좋은 해결책을 보지 못합니다. "ap"/ "apply"는 "tie fighter"만큼 모호합니다. 모든 것이 기능 응용입니다. 그러나 파란색에서 나오는 이름은 사용을 통해 의미를 얻을 수 있습니다. "Apple"이 좋은 예입니다. 그건 그렇고, Monad 반환 Applicative 순수입니다. 여기에는 발명품이 없습니다.
dmvianna
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.