형식 패밀리 또는 기능 종속성 (user2407038의 대답과 유사) 외에도 다른 대체 방법은 GADT을 사용하는 것입니다.
{-# LANGUAGE GADTs #-}
class Aggregator g where
aggregate :: g a b -> [a] -> b
data SingleAggregator a b = SingleAggregator ([a] -> b)
data DoubleAggregator a b where
DoubleAggregator :: ([a] -> b) -> ([a] -> b) -> DoubleAggregator a (b, b)
instance Aggregator SingleAggregator where
aggregate (SingleAggregator f) as = f as
instance Aggregator DoubleAggregator where
aggregate (DoubleAggregator f g) as = (f as, g as)
이 방법이 더 나은지 나쁜지는 귀하의 정확한 사용 사례에 따라 다르지만 실제로 유형 클래스 확장보다 훨씬 간단합니다.
GADT 접근법을 사용하면 하나의 대수 형식을 원할 경우 유형 클래스를 모두 삭제할 수 있습니다.
data Aggregator a b where
SingleAggregator :: ([a] -> b) -> Aggregator a b
DoubleAggregator :: ([a] -> b) -> ([a] -> b) -> Aggregator a (b, b)
aggregate :: Aggregator a b -> [a] -> b
aggregate (SingleAggregator f) as = f as
aggregate (DoubleAggregator f g) as = (f as, g as)
그러나이 접근의 아마도 가장 "하스켈-Y"방법은 단지 하나의 Aggregator
newtype은이 있고 Applicative
타입 클래스와 그 작성 가능하게했다.예를 들어 :
import Control.Applicative
newtype Aggregator a b = Aggregator { aggregate :: [a] -> b }
instance Functor (Aggregator a) where
fmap f (Aggregator g) = Aggregator (f . g)
instance Applicative (Aggregator a) where
pure = Aggregator . const
Aggregator f <*> Aggregator x = Aggregator $ f <*> x
이제
minAgg = Aggregator minimum
maxAgg = Aggregator maximum
같은 간단한 수집기를 정의 할 수 있습니다 다음 Applicative
인터페이스
minMax = liftA2 (,) minAgg maxAgg
난 당신이 취급에 특별히 관심이있는 알을 사용하여 더 복잡한 수집기로를 구성하는 이것은 클래스를 가지고 있지만,'data Aggregator a b '를 사용했다 할지라도'fold'문제와 비슷하게 들린다. ... ', 비어있는 목록이 올바르게 처리되지 않을 것 같은 것처럼 보입니다. '모노 이드 (Monoid) '와 폴드 (fold)를 살펴볼 수 있습니다. – unfoldr