gpt4 book ai didi

function - 在函数中声明函数类型

转载 作者:行者123 更新时间:2023-12-04 03:49:41 24 4
gpt4 key购买 nike

我有两个功能:

prop_merge_check :: Ord a => [a] -> [a] -> Bool
prop_merge_check xs ys = length (merge xs ys) == length (sort (xs ++ ys))

prop_unzip_check :: Ord a => [(a,b)] -> Bool
prop_unzip_check xs = length (unzip xs) >= 0

如何在函数本身中声明函数的类型?

我试过这种方式,但它对我不起作用。
prop_merge_check xs ys = length (merge (xs::[a]) (ys::[a])) 
== length (sort ( (xs::[a]) ++ (ys::[a]) ))

prop_unzip_check xs = length (unzip (xs::[(a,b)])) >= 0

最佳答案

这是 Haskell 隐式 forall 的副作用。 Haskell 会根据需要自动将 'forall' 添加到所有类型签名,这些充当“范围”规则,将名称限制在特定区域。 Haskell 将您的签名解释为:

prop_merge_check :: forall a. Ord a => [a] -> [a] -> Bool
prop_merge_check xs ys =
length (merge (xs::forall a. [a]) (ys:: forall a. [a])) == (length (sort ((xs:: forall a. [a]) ++ (ys:: forall a. [a]))))

那是;它看到每个 a在每个签名中作为一个完全不同的变量!这就是为什么它不能使类型正常工作的原因。这是一个令人讨厌且不明显的怪癖,但有一种解决方法。

如果我们启用 ScopedTypeVariables并在类型签名中提供一个明确的 forall 我们告诉 Haskell 我们希望类型变量的范围跨越整个函数体:
{-# LANGUAGE ScopedTypeVariables #-}
-- ^ Put that at the top of your module

prop_merge_check :: forall a. Ord a => [a] -> [a] -> Bool
prop_merge_check xs ys =
length (merge (xs::[a]) (ys::[a])) == (length (sort ((xs::[a]) ++ (ys::[a]))))

这个版本应该可以编译了,因为现在 a在所有签名中被认为是相同的。我们可以一次量化多个类型变量:
prop_unzip_check :: forall a b. Ord a => [(a,b)] -> Bool
prop_unzip_check xs = length (unzip (xs::[(a,b)])) >= 0

不幸的是,目前没有一种简单的方法可以在顶级签名中不添加显式 forall 的情况下执行此类操作,但是有一些建议可以更改此行为。不过,他们可能不会很快到来。所以我不会屏住你的呼吸。

祝你好运!您可以查看有关 ScopedTypeVariables 和 ExistentialQuantification 的文档以了解有关此怪癖的更多信息。

关于function - 在函数中声明函数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59022609/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com