Я наткнулся на поведение, которое я не могу объяснить в Haskell. Я пытаюсь сохранить полиморфную функцию в типе записи, которую я хочу использовать в ReaderT Monad. Когда я получаю свою функцию с asks
, компилятор не распознает ее как полиморфную и, похоже, фиксирует тип при первом возникновении функции. Я создал минимальный пример в GHCI:Полиморфные функции в типах записей Haskell
{-# LANGUAGE Rank2Types #-}
data Test = Test {f :: (forall a. a -> a)}
runReaderT (asks f
>>= \f -> (liftIO . putStrLn $ show (f 2 :: Int))
>> (liftIO . putStrLn $ show (f "hello"))
) (Test id)
При попытке запуска этого я получаю:
Couldn't match expected type ‘Int’ with actual type ‘[Char]’
In the first argument of ‘f’, namely ‘"hello"’
In the first argument of ‘show’, namely ‘(f "hello")’
In the second argument of ‘($)’, namely ‘show (f "hello")’
Однако следующий код работает:
runReaderT (ask
>>= \(Test f) -> (liftIO . putStrLn $ show (f 2 :: Int))
>> (liftIO . putStrLn $ show (f "hello"))
) (Test id)
Так это что-то специальный с asks
? Я благодарен за любые советы по этому поводу.
Я предполагаю, что он должен делать с 'f' появляется после \ если я не ошибаюсь, аргументы лямбда-прежнему мономорфным если вам в противном случае. – Ingo
Только хедз-ап: Rank2Types - это устаревшее расширение, наложенное на RankNTypes. (И RankNTypes просто позволяет вам писать 'forall'. Нет вывода более высокого ранга в GHC, так как подробности ответа Ingo.) – hao