Haskell中的隐形类型签名

时间:2014-08-30 15:37:23

标签: haskell

我想在函数中使用模糊类型a,如下所示,但它失败了。

foo :: (Read a, Show a) => IO ()
foo = print =<< (readLn :: IO a)

目的是在实际调用时获得与给定类型签名不同的输出。

>>> foo :: Double => IO ()
34   -- user input
34.0 -- output

>>> foo :: Int => IO ()
34   -- user input
34   -- output

我该如何管理?

2 个答案:

答案 0 :(得分:9)

最简单的方法是显示您的类型变量。例如,使用新的GHC:

{-# LANGUAGE ScopedTypeVariables #-}
foo :: forall proxy a. (Read a, Show a) => proxy a -> IO ()
foo _ = print (read "34" :: a)

然后,在ghci:

Data.Proxy *Main> foo (Proxy :: Proxy Double)
34.0
Data.Proxy *Main> foo (Proxy :: Proxy Int)
34

或者,一种更奇特的用法,依赖于更隐式的Haskell行为:

*Main> foo [0.0]
34.0
*Main> foo [0]
34

答案 1 :(得分:4)

foo :: Double => IO ()foo :: Int => IO ()都不是有效签名,因为DoubleInt不是约束。

但是,您可以轻松地在其返回类型中使函数具有多态性,并按以下方式编写:

foo :: (Read a, Show a) => IO a
foo = let x = read "34" in print x >> return x

这样,您可以使用foo :: IO Doublefoo :: IO Integer

ghci> foo :: IO Double
34.0 -- print
34.0 -- result, you would discard it
ghci> foo :: IO Integer
34
34