2014-08-30 72 views
2

我想在函数中使用模糊类型a,但它失败。Haskell中的隐形类型签名

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

对不起,我改变了示例函数。 – user3749167 2014-08-30 16:00:01

回答

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 

或者,更奇特的使用,依靠比较含蓄哈斯克尔行为:

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

'ScopedTypeVariables'就是我想要的! 谢谢。 – user3749167 2014-08-30 15:53:22

+0

请注意,您可以在没有'ScopedTypeVariables'的情况下执行此操作,例如定义'asProxyTypeOf :: a - >代理a - > a; asProxyTypeOf = const',然后写''foo p = print(读“34”asProxyTypeOf' p)''。 – shachaf 2014-08-30 20:08:51

+0

和SignatureSections你可以写'foo(:: Int)34'。 – augustss 2014-08-30 23:56:32

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 
+0

对不起,但这不是我打算做的。 该类型应该是'IO()' – user3749167 2014-08-30 15:52:46

+0

@ user3749167:这很容易用'void(foo :: ...)'修复。正如丹尼尔所说,另一个变种是'ScopedTypeVariables'。 – Zeta 2014-08-30 15:56:18

+0

我的实际功能要复杂得多,不能用'void'解决。 非常感谢! – user3749167 2014-08-30 16:01:24