我想在函数中使用模糊类型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
我该如何管理?
答案 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 ()
都不是有效签名,因为Double
和Int
不是约束。
但是,您可以轻松地在其返回类型中使函数具有多态性,并按以下方式编写:
foo :: (Read a, Show a) => IO a
foo = let x = read "34" in print x >> return x
这样,您可以使用foo :: IO Double
或foo :: IO Integer
:
ghci> foo :: IO Double
34.0 -- print
34.0 -- result, you would discard it
ghci> foo :: IO Integer
34
34