是否有可能以某种方式使下面的代码片段更通用,我们基本上有2个函数具有相同的代码,唯一的区别是函数定义,是否有可能以某种方式抽象出来
unsafeListHandling :: [a] -> ([a] -> a) -> Maybe a
unsafeListHandling xs fx = if null xs then Nothing else Just $ fx xs
unsafeListHandling2 :: [a] -> ([a] -> [a]) -> Maybe [a]
unsafeListHandling2 xs fx = if null xs then Nothing else Just $ fx xs
答案 0 :(得分:3)
this one等答案涵盖了系统的方法。但在许多情况下,仔细查看我们对类型签名的了解是我们需要弄清楚的。
unsafeListHandling :: [a] -> ([a] -> a ) -> Maybe a unsafeListHandling2 :: [a] -> ([a] -> [a]) -> Maybe [a]
我们对广义unsafeListHandling
知道的事情:
Maybe
。如果我们将其作为类型签名写下来,我们得到:
unsafeListHandling :: [a] -> ([a] -> b) -> Maybe b
a
是任意的b
,b ~ [a]
和b ~ a
都是有效的专精。如果我们将b
视为一个自由且不受约束的类型变量,我们可以看到没有什么能阻止我们将它专门化为[a]
或a
;如此,一般类型签名确实是:
unsafeListHandling :: [a] -> ([a] -> b) -> Maybe b
unsafeListHandling xs fx = if null xs then Nothing else Just $ fx xs
如果我们遵循melpomene的建议,并在不添加任何签名的情况下向GHCi询问您的功能类型......
GHCi> :t \xs fx -> if null xs then Nothing else Just $ fx xs
\xs fx -> if null xs then Nothing else Just $ fx xs
:: Foldable t => t a -> (t a -> a1) -> Maybe a1
...除了[a]
到Foldable t => t a
的无关紧要的概括之外,我们得到了这一点,因为null
的类型是Foldable t => t a -> Bool
。顺便说一句,如果您使用的是GHC 8,则可以启用TypeApplications
扩展程序,并将其用作为您的类型俄罗斯方块专门化null
的便捷方式:
GHCi> :set -XTypeApplications
GHCi> :t \xs fx -> if null @[] xs then Nothing else Just $ fx xs
\xs fx -> if null @[] xs then Nothing else Just $ fx xs
:: [a] -> ([a] -> a1) -> Maybe a1
总结一下,广义函数实际上做了你想做的事情的演示:
GHCi> (\xs fx -> if null @[] xs then Nothing else Just $ fx xs) [1..7] head
Just 1
GHCi> (\xs fx -> if null @[] xs then Nothing else Just $ fx xs) [1..7] tail
Just [2,3,4,5,6,7]