#haskell #ghc
#хаскелл #ghc
Вопрос:
Следующий код компилируется, но только с явной сигнатурой типа в bar
:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
type family ResultOf a where
ResultOf (a -> b) = ResultOf b
ResultOf a = a
wrap :: (Monad rnd, ResultOf bnch ~ rnd Int) => bnch -> rnd Int
wrap = undefined
foo :: (Monad m) => m Int
foo = undefined
bar :: forall rnd . (Monad rnd, ResultOf (rnd Int) ~ rnd Int) => rnd Int
bar = wrap (foo :: rnd Int)
Я примерно понимаю, почему требуется подпись типа: foo
является полиморфной, и GHC не может сказать, что единственный способ ResultOf (forall m . (MonadRandom m) => m Int) ~ rnd Int
— это создать экземпляр m
at rnd
. Я бы хотел, чтобы это было правдой, чтобы GHC мономорфизировал ‘foo` с правильной монадой без явной подписи типа. Есть ли какой-нибудь способ убедить GHC в этом?
Комментарии:
1. Одним из решений является использование newtype в качестве выходных данных функции, чтобы семейство типов не перекрывалось (т. Е. Могло существовать как открытое семейство). Можно ли это сделать без глупой оболочки, которая просто продолжается и сразу же возвращается?
2. У вас есть реальная реализация для
wrap
? Мне кажется, что эта функция населена толькоconst ...
(и, конечно, различными днищами).ResultOf a ~ a
утверждает, чтоa
это не тип функции, потому что это не может быть правдой, если первый шаблон когда-либо совпадал, но он не содержит доказательства этого — вы должны построить это самостоятельно. Обычно способ сделать это — написать GADT, моделирующий доказательство, и иметь класс типа, который неявно создает значения этого доказательства.3. @user2407038
wrap
использует простой класс типов (не показан, поскольку он не имеет отношения к проблеме вывода) для случайной генерации аргументов функции, очень похожих на тестируемый класс QuickCheck.