在 Haskell 脚本中,如何以编程方式获取函数的类型签名?
In a Haskell script, how does one programatically obtain the type signature of a function?
在 Haskell (GHC) 中,如何获得下面显示的函数列表的类型签名?
[tail,init,reverse]
我尝试使用 Data.Typeable
模块的 typeOf
函数失败。具体来说,我尝试 运行 以下 Haskell 脚本:
import Data.Typeable
import Test.HUnit
myTest = TestCase
( assertEqual "\n\nShould have been \"[[a] -> [a]]\""
"[[a] -> [a]]"
(show ( typeOf [tail,init,reverse] )) )
tests = TestList [ (TestLabel "myTest" myTest) ]
但是,GHC 响应以下错误:
C:\>ghci my_script.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( my_script.hs, interpreted )
my_script.hs:7:21: error:
* No instance for (Typeable a0) arising from a use of `typeOf'
* In the first argument of `show', namely
`(typeOf [tail, init, reverse])'
In the third argument of `assertEqual', namely
`(show (typeOf [tail, init, reverse]))'
In the first argument of `TestCase', namely
`(assertEqual
"\n\
\n\
\Should have been \"[[a] -> [a]]\""
"[[a] -> [a]]"
(show (typeOf [tail, init, reverse])))'
Failed, modules loaded: none.
Prelude>
更新: 下面的 HUnit 测试用例不是我想要的,但我确实让它通过了(基于 David Young 的建议)。这个测试用例至少强制编译器确认 [tail,init,reverse]
是 [ [a] -> [a] ]
.
类型
import Data.Typeable
import Test.HUnit
myTest = TestCase
( assertEqual "\n\nShould have been 3"
3
( length ( [tail,init,reverse] :: [[a]->[a]] ) ) )
tests = TestList [ (TestLabel "myTest" myTest) ]
C:\>my_script.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( my_script.hs, interpreted )
Ok, modules loaded: Main.
*Main> runTestTT tests
Cases: 1 Tried: 1 Errors: 0 Failures: 0
您不需要单元测试来检查函数的类型。代码编译后运行秒进行单元测试,属于动态测试。但是,类型检查是一种静态测试:所有类型都在程序编译期间进行测试。因此,我们可以将 GHC 用作最小的静态类型检查器,并将您的程序缩减为:
main :: IO ()
main = return ()
where
tailInitReverseAreListFunctions :: [[a] -> [a]]
tailInitReverseAreListFunctions = [tail, init, reverse]
当您实际使用真实数据测试您的函数时,您甚至不再需要该测试,因为该应用程序也会(静态)测试函数的类型。
记住,Haskell 是一种静态类型语言。在编译期间检查类型,before 你的代码是 运行。因此,任何类型检查单元测试或多或少都是一种代码味道,因为它只能通过。
在 Haskell (GHC) 中,如何获得下面显示的函数列表的类型签名?
[tail,init,reverse]
我尝试使用 Data.Typeable
模块的 typeOf
函数失败。具体来说,我尝试 运行 以下 Haskell 脚本:
import Data.Typeable
import Test.HUnit
myTest = TestCase
( assertEqual "\n\nShould have been \"[[a] -> [a]]\""
"[[a] -> [a]]"
(show ( typeOf [tail,init,reverse] )) )
tests = TestList [ (TestLabel "myTest" myTest) ]
但是,GHC 响应以下错误:
C:\>ghci my_script.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( my_script.hs, interpreted )
my_script.hs:7:21: error:
* No instance for (Typeable a0) arising from a use of `typeOf'
* In the first argument of `show', namely
`(typeOf [tail, init, reverse])'
In the third argument of `assertEqual', namely
`(show (typeOf [tail, init, reverse]))'
In the first argument of `TestCase', namely
`(assertEqual
"\n\
\n\
\Should have been \"[[a] -> [a]]\""
"[[a] -> [a]]"
(show (typeOf [tail, init, reverse])))'
Failed, modules loaded: none.
Prelude>
更新: 下面的 HUnit 测试用例不是我想要的,但我确实让它通过了(基于 David Young 的建议)。这个测试用例至少强制编译器确认 [tail,init,reverse]
是 [ [a] -> [a] ]
.
import Data.Typeable
import Test.HUnit
myTest = TestCase
( assertEqual "\n\nShould have been 3"
3
( length ( [tail,init,reverse] :: [[a]->[a]] ) ) )
tests = TestList [ (TestLabel "myTest" myTest) ]
C:\>my_script.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( my_script.hs, interpreted )
Ok, modules loaded: Main.
*Main> runTestTT tests
Cases: 1 Tried: 1 Errors: 0 Failures: 0
您不需要单元测试来检查函数的类型。代码编译后运行秒进行单元测试,属于动态测试。但是,类型检查是一种静态测试:所有类型都在程序编译期间进行测试。因此,我们可以将 GHC 用作最小的静态类型检查器,并将您的程序缩减为:
main :: IO ()
main = return ()
where
tailInitReverseAreListFunctions :: [[a] -> [a]]
tailInitReverseAreListFunctions = [tail, init, reverse]
当您实际使用真实数据测试您的函数时,您甚至不再需要该测试,因为该应用程序也会(静态)测试函数的类型。
记住,Haskell 是一种静态类型语言。在编译期间检查类型,before 你的代码是 运行。因此,任何类型检查单元测试或多或少都是一种代码味道,因为它只能通过。