2016-03-06 1 views
2

Рассмотрим следующие две функции в Haskell (минимальный пример моего реального кода):типы необходимых эквивалентными через два отдельных вызова функции

printSequence :: (Show a, Show b) => a -> b -> IO() 
printSequence x y = (putStr . show) x >> (putStr . show) y 

printSequence' :: (Show a, Show b) => a -> b -> IO() 
printSequence' x y = print' x >> print' y 
    where print' = putStr . show 

Первый компилируется нормально, но второй производит ошибку:

Could not deduce (a ~ b) 
    from the context (Show a, Show b) 
     bound by the type signature for 
       printSequence' :: (Show a, Show b) => a -> b -> IO() 
     at test.hs:8:19-53 
     `a' is a rigid type variable bound by 
      the type signature for 
      printSequence' :: (Show a, Show b) => a -> b -> IO() 
      at test.hs:8:19 
     `b' is a rigid type variable bound by 
      the type signature for 
      printSequence' :: (Show a, Show b) => a -> b -> IO() 
      at test.hs:8:19 
    In the first argument of print', namely `y' 
    In the second argument of `(>>)', namely `(print' y)' 
    In the expression: (print' x) >> (print' y) 

Я понимаю эту ошибку, означает, что GHC требует, x и y быть эквивалентным типа. Я не понимаю, почему. Заявления вроде print "fish" >> print 3.14 работают отлично в интерпретаторе, так почему GHC жалуется на x и y - разные типы, когда я вызываю функцию print' два раза раз?

+1

О страшном Мономорфизм Ограничение: http://stackoverflow.com/ questions/32496864/what-is-the-monomorphism-restriction – chi

ответ

1

добавить явный тип подписи:

printSequence' :: (Show a, Show b) => a -> b -> IO() 
printSequence' x y = print' x >> print' y 
    where 
    print' :: Show a => a -> IO() 
    print' = putStr . show 

или использовать NoMonomorphismRestriction:

{-# LANGUAGE NoMonomorphismRestriction #-} 

printSequence' :: (Show a, Show b) => a -> b -> IO() 
printSequence' x y = print' x >> print' y 
    where 
    print' = putStr . show 

тогда

\> printSequence' 5 "five" 
5"five" 
+0

Это работает при копировании дословно, но У меня есть следующий вопрос относительно вашего первого решения. Почему это происходит, когда я предоставляю подпись типа в той же строке, например 'where print '= (putStr. Show) :: Показать a => a -> IO()'? – ApproachingDarknessFish

+1

@ApproachingDarknessFish Это аннотирует значение в правой части знака =, оставляя GHC для вывода типа имени в левой части. GHC отображает мономорфные типы для шаблонов без явных аргументов функции, а объявление полиморфного типа справа не изменяет это правило. – amalloy

Смежные вопросы