Это не то, что означает ограничение мономорфизма. Ограничение мономорфизма гласит, что если определение не имеет сигнатуры типа и имеет левую сторону без параметров, оно будет специализировано для мономорфного типа (или, скорее, достаточно мономорфного, чтобы избавиться от любых ограничений класса). Вы дали подписи типа, чтобы он не применялся.
Проблема в том, что вы указали неверный тип на f
.
f :: IO (a -> IO String)
фактически означает
f :: forall a. IO (a -> IO String)
То есть, первого выбрать тип a
, то вы можете связать, чтобы получить мономорфическую функцию типа a -> IO String
для этого a
. Там нет никаких проблем с этой программой, например:
main = do
g <- f
g "String" >>= print
g' <- f
g' 5 >>= print
Но ваш пример использования требует такого типа:
f :: IO (forall a. a -> IO String)
То есть, вы хотите связать первый и выбрать тип позже, т.е. использовать функция на нескольких типах. Это называется «непроизводительным типом», и, к сожалению, GHC не поддерживал их довольно долго, насколько мне известно.
Путь к решению этой проблемы, чтобы сделать newtype
оболочку, которая явно количественно внутренний полиморфный тип:
newtype R = R { getR :: forall a. a -> IO String }
f :: IO R
f = return $ R (const getLine)
main :: IO()
main = do
g <- f
getR g "String" >>= print
getR g 5 >>= print
Спасибо! Я не был уверен, что это ограничение мономорфизма или нет, и самое близкое, что я мог найти, это «NoMonoPatBinds», но это тоже не помогло. – Fraser
Стоит отметить, что единственные обитатели типа 'forall a. a -> IO String' являются элементами формы '\ _ -> x', где' x :: IO String'. Если для простоты нет дополнительной информации, то «R» должно быть просто «newtype R = R (IO String)», и в этом случае его можно обойти полностью. – user2407038