나는 " 하스켈을 배울 때 내가 알았 으면하는 것 "이라는 책을 읽고 있었고이 예제를 중단했습니다.
class Bifunctor p where
bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
first :: (a -> b) -> p a c -> p b c
second :: (b -> c) -> p a b -> p a c
내 질문은 : 어떻게 그 클래스의 인스턴스를 만들 수 있습니까? 아이디어는 함수를 다음과 같이 호출하는 것입니다.
λ bimap (+1) (+2) (8, 9) -- (9, 11)
λ first (*4) (10, 8) -- (40, 8)
λ second (*2) (3, 5) -- (3, 10)
이것을 달성하기 위해 가장 가까운 것은 다음과 같습니다.
instance Bifunctor (x, y) where
bimap func func' (x, y) = (func x, func' y)
first func (x, y) = (func x, y)
second func (x, y) = (x, func y)
하지만 작동하지 않고 오류가 발생합니다.
• Expecting two fewer arguments to ‘(x, y)’
Expected kind ‘* -> * -> *’, but ‘(x, y)’ has kind ‘*’
• In the first argument of ‘Bifunctor’, namely ‘(x, y)’
In the instance declaration for ‘Bifunctor (x, y)’
좋은 질문.
클래스는 펑터 유형 자체에 적용되며 귀하의 경우 펑터 유형은 (,)입니다. 그것에 대한 느낌을 얻으려면 여기에서 차이점을 확인하십시오.
:t (,)
(,) :: a -> b -> (a, b)
:t (True,False)
(True,False) :: (Bool, Bool)
다음과 같은 쌍 유형을 사용했다면 더 직관적이었을 것입니다.
data Pair a b = Pair a b
클래스 정의를 읽으면 'p'의 유형 적용이 더 분명해 졌기 때문입니다.
Haskell이 위에서 설명한 것처럼 값에 유형을 사용하는 것처럼 Kinds 라는 유형의 유형 (컴파일 시간 논리에도 해당)을 사용 합니다.
:k Pair
Pair :: * -> * -> *
:k (,)
(,) :: * -> * -> *
:k (Bool,Bool)
(Bool,Bool) :: *
:k Bifunctor
Bifunctor :: (* -> * -> *) -> Constraint
이 마지막 줄은 Bifunctor 클래스가 (a, b) (* -> * -> *)
종류 (*)
가 아닌 종류 유형을 위해 설계 되었으므로 GHC에서받은 오류 메시지를 보여줍니다.
귀하의 정의는 거의 맞았습니다. 여기에 올바른 정의가 있습니다.
instance Bifunctor (,) where
bimap func func' (x, y) = (func x, func' y)
first func (x, y) = (func x, y)
second func (x, y) = (x, func y)
편집 : @leftroundabout에서 제안한 종류의 그림
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다