Haskell Prelude에서 'const'의 요점은 무엇입니까?


94

Haskell Prelude를 살펴보면 다음과 같은 기능이 있습니다 const .

const x _ = x

이 기능과 관련된 어떤 것도 찾을 수없는 것 같습니다.

점은 무엇인가? 누구든지이 기능이 어디에서 사용될 수 있는지 예를 들어 줄 수 있습니까?


10
예 : backgroundColor :: Text -> Color나를 위해입니다backgroundColor = const White

답변:


83

유연성이 모두 필요하지 않을 때 고차 함수로 전달하는 데 유용합니다. 예를 들어, 모나 딕 시퀀스 연산자 >>는 모나 딕 바인딩 연산자 측면에서 다음과 같이 정의 할 수 있습니다.

x >> y = x >>= const y

람다를 사용하는 것보다 다소 깔끔합니다.

x >> y = x >>= \_ -> y

포인트없이 사용할 수도 있습니다.

(>>) = (. const) . (>>=)

이 경우 특별히 권장하지는 않지만.


9
+1. 파서 결합자를 사용할 때도 자주 나타납니다.
Fred Foo

48
Ahh 그래서 그것은 '함수 발생기'에 가깝습니다. 하나의 인수와 함께 사용하고 항상 상수 값을 반환하는 함수 (하나의 인수를 사용함)를 제공합니다. 그래서 map (const 42) [1..5]결과 [42, 42, 42, 42, 42].
stusmith

2
stusmith : 알겠습니다. const단일 인수에 적용하여 필요한 함수 (예 :에 전달 map) 를 생성하는 데 유용합니다 .
Conal

8
@stusmith : 몇 가지 흥미로운 방법으로 사용할 수 있습니다.head = foldr const (error "Prelude.head: empty list")
rampion

27

HAMMAR의 우수한 직접 대답에 추가하려면 겸손 기능이 좋아 const하고 id그들이 것과 같은 이유로 고차 함수로 정말 유용한 기본적인 에서 스키 콤비 미적분학 .

나는 하스켈의 전주곡 기능이 그 공식적인 시스템이나 그 어떤 것을 의식적으로 모델화했다고 생각하지 않는다. 하스켈에서 풍부한 추상화를 만드는 것은 매우 쉬우므로 이러한 유형의 이론적 인 것이 실제로 유용하게 나타나는 것을 종종 볼 수 있습니다.

뻔뻔한 플러그,하지만 난에 대한 실용적 인스턴스 방법에 대해 블로그에 (->)실제로있는 SK연결자 여기 가 당신이에있어 물건의 종류의 경우.


8
음, SKI 결합자는 확실히 Prelude에 영향을 미쳤습니다. 나는 S 조합이 포함되어야하는지 아닌지에 대해 Joe Fasel과 논쟁을 벌였던 것을 기억한다.
8

4
우연히도 ((->) e)리더 모나드 Readernewtype래퍼 일 뿐이며 ask함수는 id이므로 I결합 자이기도합니다. 당신이 하스켈 카레의 원래 BCKW 기준에 대신 보면 B, K하고 W있다 fmap, return그리고 join각각.
CA McCann 2011 년

1
답변의 블로그 링크가 죽었습니다. 그것은 지금 여기 가리켜 야 : brandon.si/code/...을
nsxt

22

사용에 대한 간단한 예 constData.Functor.(<$). 이 함수를 사용하면 다음과 같이 말할 수 있습니다. 여기에 지루한 무언가가있는 펑터가 있지만 대신 펑터의 모양을 변경하지 않고 다른 흥미로운 것을 포함하고 싶습니다. 예

import Data.Functor

42 <$ Just "boring"
--> Just 42

42 <$ Nothing
--> Nothing

"cool" <$ ["nonsense","stupid","uninteresting"]
--> ["cool","cool","cool"]

정의는 다음과 같습니다.

(<$) :: a -> f b -> f a
(<$) =  fmap . const

또는 무의미하게 작성되지 않았습니다.

cool <$ uncool =  fmap (const cool) uncool

const여기에서 입력에 대해 "잊기"위해 사용되는 방법을 볼 수 있습니다 .


21

이 기능과 관련된 어떤 것도 찾을 수없는 것 같습니다.

다른 많은 답변은 상대적으로 난해한 (최소한 신규 사용자에게는) const. 다음은 간단한 것입니다. const두 개의 인수를 취하고 첫 번째 인수를 버리지 만 두 번째 인수에서 흥미로운 일을하는 람다를 제거하는 데 사용할 수 있습니다 .

예를 들어, 다음 (비효율적이지만 유익한) 구현은 length,

length' = foldr (\_ acc -> 1 + acc) 0

다음과 같이 다시 작성할 수 있습니다.

length' = foldr (const (1+)) 0

아마도 더 우아 할 것입니다.

표현식 const (1+)\_ acc -> 1 + acc하나의 인수를 취하고 버리고 섹션을 반환하기 때문에 실제로 의미 상으로 동일합니다 (1+).


4
이것이 :) 어떻게 작동하는지 이해 5 분 걸렸다
무 케시 SONI에게

15

또 다른 용도는 평가해서는 안되는 더미 인수 (모호한 유형을 해결하는 데 사용됨)가있는 클래스 멤버 함수를 구현하는 것입니다. Data.bits에있을 수있는 예 :

instance Bits Int where
  isSigned = const True
  bitSize  = const wordSize
  ...

const를 사용함으로써 우리는 상수 값을 정의하고 있다고 명시 적으로 말합니다.

개인적으로 나는 더미 매개 변수의 사용을 싫어하지만, 그들이 클래스에서 사용된다면 이것은 인스턴스를 작성하는 다소 좋은 방법입니다.


프록시 인수는 실제로 훨씬 낫고 최근 GHC를 대상으로 할 때 유형 응용 프로그램이 트릭을 깔끔하게 수행합니다.
dfeuer

2

const다른 기능과 함께 찾고있는 구현 일 수도 있습니다. 여기 내가 발견 한 예가 있습니다.

2- 튜플 구조를 다른 2- 튜플 구조로 다시 작성하고 싶다고 가정 해 보겠습니다. 나는 이것을 다음과 같이 표현할 수있다.

((a,b),(c,d)) ⇒ (a,(c,(5,a)))

패턴 일치를 사용하여 간단한 정의를 제공 할 수 있습니다.

f ((a,b),(c,d)) = (a,(c,(5,a)))

이런 종류의 재 작성에 대해 무의미한 (암묵적인) 솔루션을 원한다면 어떻게합니까? 나중에 약간의 생각과 조롱 거리는 대답은 우리가 어떤 재 작성도 표현할 수 있다는 것입니다 (&&&), const, (.), fst, snd. 출처 (&&&)Control.Arrow.

이러한 함수를 사용하는 예제의 솔루션은 다음과 같습니다.

(fst.fst &&& (fst.snd &&& (const 5 &&& fst.fst)))

와의 유사점에 유의하십시오 (a,(c,(5,a))). 로 대체 &&&하면 ,어떨까요? 그런 다음 읽습니다.

(fst.fst, (fst.snd, (const 5, fst.fst)))

a첫 번째 요소의 첫 번째 요소가 어떻게 fst.fst프로젝트 인지 주목 하십시오 . c두 번째 요소의 첫 번째 요소가 어떻게 fst.snd프로젝트 인지 주목 하십시오 . 즉, 변수는 소스의 경로가됩니다.

const상수를 도입 할 수 있습니다. 이름이 의미와 어떻게 일치하는지 흥미 롭습니다!

당신이 무의미 스타일의 모든 기능을 쓸 수 있도록 그때 (너무 오래 사용하면 다음과 같은 기능, 같은 사례 분석을 사용할 수 있습니다로 실용적으로이 아이디어를 일반화 maybe, either, bool). 다시, const상수를 도입하는 역할을합니다. 이 작업은 Data.Function.Tacit 패키지 에서 볼 수 있습니다 .

추상적으로 목표에서 시작한 다음 구현을 향해 작업 할 때 대답에 놀랄 수 있습니다. 즉, 하나의 기능은 기계의 톱니 바퀴만큼 신비 할 수 있습니다. 그러나 전체 기계를보기 위해 뒤로 당기면 해당 톱니 바퀴가 필요한 컨텍스트를 이해할 수 있습니다.


2

Nothings문자열 길이와 동일한 목록을 만들고 싶다고 가정 해 보겠습니다 . As const는 첫 번째 인수를 반환하며 두 번째 인수에 관계없이 다음을 수행 할 수 있습니다.

listOfNothings :: String -> [Maybe Char]
listOfNothings = (map . const) Nothing

또는 더 명시 적으로 :

listOfNothing st = map (const Nothing) st

0

목록을 회전하고 싶다고 가정 해 보겠습니다. 이것은 Haskell에서 그렇게하는 관용적 인 방법입니다 :

rotate :: Int -> [a] -> [a] rotate _ [] = [] rotate n xs = zipWith const (drop n (cycle xs)) xs

이 함수는 함수를 사용하여 두 개의 배열을 압축 const합니다. 첫 번째는 무한 순환 배열이고 두 번째는 시작한 배열입니다.

const 경계 검사 역할을하며 원래 배열을 사용하여 순환 배열을 종료합니다.

참조 : Haskell에서 목록 회전


0

이 기능과 관련된 어떤 것도 찾을 수없는 것 같습니다.

주어진 목록의 모든 하위 시퀀스를 생성한다고 가정합니다.

각 목록 요소에 대해 주어진 지점에서 True (현재 하위 시퀀스에 포함) 또는 False (포함하지 않음)를 선택할 수 있습니다. filterM 함수를 사용하여 수행 할 수 있습니다 .

이렇게 :

 λ> import Control.Monad
 λ> :t filterM
 filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
 λ> 

예를 들어, 우리는의 모든 하위 시퀀스를 원합니다 [1..4].

 λ> filterM  (const [True, False])  [1..4]
 [[1,2,3,4],[1,2,3],[1,2,4],[1,2],[1,3,4],[1,3],[1,4],[1],[2,3,4],[2,3],[2,4],[2],[3,4],[3],[4],[]]
 λ> 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.