Haskell类型检查代码

时间:2017-03-26 23:09:48

标签: haskell

您能否告诉我如何在不在命令页面的代码中检查func的类型是否为Tree

data Tree = Leaf Float | Gate [Char] Tree Tree deriving (Show, Eq, Ord)
func a = Leaf a

2 个答案:

答案 0 :(得分:2)

嗯,有一些答案,在答案中曲折,这是可能的"。

  1. 您可以问ghci

    ghci> :t func
    func :: Float -> Tree
    

    告诉你类型。

  2. 但是你在评论中说你想要写

    if func == Tree then 0 else 1
    

    这是不可能的。特别是,你不能写任何像

    这样的函数
    isTree :: a -> Bool
    isTree x = if x :: Tree then True else False
    

    因为它会违反 parametericity ,这是Haskell中所有多态函数都具有的一个简洁属性,在文章Theorems for Free中进行了探讨。

  3. 可以使用一些弹出的简单通用机制来编写这样的函数;实际上,如果你想在运行时知道某些东西的类型,它需要有一个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)
    
  4. 但根据我的经验,你可能实际上并不需要提出这个问题。在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 ->,在这种情况下SomeTypeFloat。 (因为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,因此询问如何检查是否真的没有意义。