您能否告诉我如何在不在命令页面的代码中检查func
的类型是否为Tree
?
data Tree = Leaf Float | Gate [Char] Tree Tree deriving (Show, Eq, Ord)
func a = Leaf a
答案 0 :(得分:2)
嗯,有一些答案,在答案中曲折,这是可能的"。
您可以问ghci
ghci> :t func
func :: Float -> Tree
告诉你类型。
但是你在评论中说你想要写
if func == Tree then 0 else 1
这是不可能的。特别是,你不能写任何像
这样的函数isTree :: a -> Bool
isTree x = if x :: Tree then True else False
因为它会违反 parametericity ,这是Haskell中所有多态函数都具有的一个简洁属性,在文章Theorems for Free中进行了探讨。
但可以使用一些弹出的简单通用机制来编写这样的函数;实际上,如果你想在运行时知道某些东西的类型,它需要有一个Typeable
约束(来自模块Data.Typeable
)。几乎每个类型都是Typeable
- 我们只是使用约束来指示违反参数,并向编译器指示它需要传递运行时类型信息。
import Data.Typeable
import Data.Maybe (isJust)
data Tree = Leaf Float | ...
deriving (Typeable) -- we need Trees to be typeable for this to work
isTree :: (Typeable a) => a -> Bool
isTree x = isJust (cast x :: Maybe Tree)
但根据我的经验,你可能实际上并不需要提出这个问题。在Haskell中,这个问题比其他语言要少得多。但我无法确定,除非我知道你要通过询问来完成什么。
答案 1 :(得分:0)
以下是如何确定Haskell中绑定的类型:取f a1 a2 a3 ... an = someExpression
之类的内容并将其转换为f = \a1 -> \a2 -> \a3 -> ... \an -> someExpression
。然后在右侧找到表达式的类型。
要查找表达式的类型,只需为每个lambda添加SomeType ->
,其中SomeType
是绑定变量的适当类型。然后使用剩余(lambda-less)表达式中的已知类型来查找其实际类型。
对于您的示例:func a = Leaf a
变为func = \a -> Leaf a
。现在要找到\a -> Leaf a
的类型,我们为lambda添加SomeType ->
,在这种情况下SomeType
为Float
。 (因为Leaf :: Float -> Tree
,所以如果将Leaf
应用于a
,那么a :: Float
)这会给我们Float -> ???
现在我们找到lambda-less表达式Leaf (a :: Float)
的类型,Tree
因为Leaf :: Float -> Tree
。现在,我们可以为Tree
添加替换???
以获取Float -> Tree
func
的实际类型。
正如您所看到的,我们通过查看源代码完成了所有操作。这意味着无论如何,func
将始终具有该类型,因此无需检查它是否具有该类型。实际上,编译器在编译代码时会丢弃有关func
类型的所有信息,并且由于类型检查,代码仍然可以正常工作。 (对此(Typeable
)的警告在另一个答案中指出)
TL; DR :Haskell是静态类型的,因此func
始终的类型为Float -> Tree
,因此询问如何检查是否真的没有意义。