Почему <*> экземпляра Const принимает два нефункциональных значения?

(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Const :: a -> Const a b
Monoid m => Applicative (Const * m)

Const "a" <*> Const "b" -- yields Const "ab"
Const a <*> Const a = Const a <> Const a

Я предполагаю, что это поведение должно быть связано с тем, что Const конструктор двоичного типа, где b никогда не трогать (фантомный тип). Но опять же я не понимаю Const * m, так как a (а также * соответственно) похоже отбрасывается в этом случае.

1 ответ

Решение

Сначала если m имеет Monoid экземпляр, то Const m имеет Applicative пример. Но Const m все еще является конструктором типа, поэтому тип <*>за Applicative (Const m) читает

     (<*>) :: Const m (a -> b) -> Const m a -> Const m b  

Теперь давайте применим это к Const "a" а также Const "b":

Const "a" имеет тип Const String b, Так вот переменная типа m сверху предполагает тип String, Значение по-прежнему полиморфно по отношению к b и так как он не содержит конкретного значения этого типа, тип может быть любым.

В выражении Const "a" <*> Const "b" полиморфное значение Const "a" будет вынужден быть типа Const String (a->b) и полиморфное значение Const "b" будет вынужден быть типа Const String a,

Таким образом, действительно есть тип с типом функции внутри с левой стороны, просто конкретное значение не содержит функции, как со значением Nothing типа Maybe (Int -> Int),

PS: я не знаю, где * приходит из Monoid m => Applicative (Const * m), Если я наберу

    :info Const

в GHCI я понимаю

    instance Monoid m => Applicative (Const m)
Другие вопросы по тегам