문제

에 따르면 TypeClassopedia (다른 출처 중에서), Applicative 논리적으로 사이에 속합니다 Monad 그리고 Pointed (따라서 Functor) Class 계층 유형에서 Haskell Prelude가 오늘 작성된 경우 이상적으로 이와 같은 것을 가지고 있습니다.

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

class Functor f => Pointed f where
    pure :: a -> f a

class Pointed f => Applicative f where
    (<*>) :: f (a -> b) -> f a -> f b

class Applicative m => Monad m where
    -- either the traditional bind operation
    (>>=) :: (m a) -> (a -> m b) -> m b
    -- or the join operation, which together with fmap is enough
    join :: m (m a) -> m a
    -- or both with mutual default definitions
    f >>= x = join ((fmap f) x)
    join x = x >>= id
    -- with return replaced by the inherited pure
    -- ignoring fail for the purposes of discussion

(그 기본 정의가 Wikipedia의 설명, 오류는 내 자신의 것이지만 오류가 있으면 원칙적으로 가능합니다.)

라이브러리가 현재 정의되어 있으므로 다음과 같습니다.

liftA :: (Applicative f) => (a -> b) -> f a -> f b
liftM ::       (Monad m) => (a -> b) -> m a -> m b

그리고:

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
ap    ::       (Monad m) => m (a -> b) -> m a -> m b

각 쌍 내에서 이러한 유형 간의 유사성에 유의하십시오.

내 질문은 다음과 같습니다 liftM (구별 liftA) 그리고 ap (구별 <*>), 단순히 역사적 현실의 결과 Monad 함께 설계되지 않았습니다 Pointed 그리고 Applicative 염두에두고? 아니면 다른 행동 방식 (잠재적으로 법적으로 Monad 정의) Applicative 문맥?

그들이 뚜렷하다면, 당신은 간단한 정의 세트를 제공 할 수 있습니까 (필요한 법률에 따라 Monad, Applicative, Pointed, 그리고 Functor TypeClassopedia와 다른 곳에서 설명했지만 유형 시스템에 의해 시행되지는 않는 정의) liftA 그리고 liftM 다르게 행동합니까?

대안으로, 그들이 뚜렷하지 않은 경우, 당신은 구내와 동일한 법률을 사용하여 동등성을 증명할 수 있습니까?

도움이 되었습니까?

해결책

liftA, liftM, fmap, 그리고 . ~해야 한다 모두 같은 기능입니다 ~ 해야 하다 그들이 Functor 법을 만족시키는 경우 :

fmap id = id

그러나 이것은 Haskell에서 확인하지 않습니다.

이제 적용을 위해. 가능합니다 ap 그리고 <*> 유형과 법률을 만족시키는 하나 이상의 구현이있을 수 있기 때문에 일부 기능자에게는 구별됩니다. 예를 들어, 목록에는 둘 이상이 가능합니다 Applicative 사례. 다음과 같이 응용 프로그램을 선언 할 수 있습니다.

instance Applicative [] where
  (f:fs) <*> (x:xs) = f x : fs <*> xs
  _      <*> _      = []
  pure              = repeat

그만큼 ap 함수는 여전히 다음과 같이 정의됩니다 liftM2 id, 그것이 Applicative 매번 무료로 제공되는 인스턴스 Monad. 그러나 여기에는 하나 이상의 유형 생성자의 예가 있습니다. Applicative 예는 모두 법을 만족시킵니다. 그러나 당신의 모나드와 응용 기능이 동의하지 않는다면, 다른 유형을 갖는 것이 좋은 형태로 간주됩니다. 예를 들어, Applicative 위의 사례는 Monad와 동의하지 않습니다 [], 그래서 당신은 정말로 말해야합니다 newtype ZipList a = ZipList [a] 그런 다음 새 인스턴스를 만듭니다 ZipList 대신에 [].

다른 팁

그들 ~할 수 있다 다르지만 그렇지 않아야합니다.

그들은 다른 구현을 가질 수 있기 때문에 다를 수 있습니다. 하나는 instance Applicative 다른 하나는 an에 정의되어 있습니다 instance Monad. 그러나 그들이 실제로 다르면, 나는 그 사례를 쓴 프로그래머가 오해의 소지가있는 코드를 썼다고 말할 것입니다.

당신이 옳습니다 : 기능은 역사적 이유로 그들이하는 것처럼 존재합니다. 사람들은 사물이어야했던 것에 대한 강한 아이디어를 가지고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top