Tim*_*rry 23 haskell type-signature
编译时收到以下错误消息:
重复类型签名:
weightedMedian.hs:71:0-39:findVal :: [ValPair] - > Double - > Double
weightedMedian.hs:68:0-36:findVal :: [ValPair] - > Int - > Double
我的解决方案是找到findValI和findValD.但是,findValI只是将Int类型转换为Double并调用findValD.
另外我不能在Num(Int,Double)类型上进行模式匹配,所以我不能只将类型签名更改为
findVal :: [ValPair] -> Num -> Double
Run Code Online (Sandbox Code Playgroud)
在许多语言中,我不需要不同的名称.为什么我在Haskell中需要不同的名字?这会很难添加到语言中吗?或者那里有龙吗?
scl*_*clv 33
Haskell中的类型类提供了特殊的多态(和名称重载):
class CanFindVal a where
findVal :: [ValPair] -> a -> Double
instance CanFindVal Double where
findVal xs d = ...
instance CanFindVal Int where
findVal xs d = findVal xs (fromIntegral d :: Double)
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,由于findVal"真的"需要a Double,我只需要一个双倍,当我需要传递一个int时,只需fromIntegral在调用站点使用.当涉及实际上不同的行为或逻辑而不是混杂时,通常需要类型类.
Phi*_* JF 16
支持这两者findVal :: [ValPair] -> Double -> Double并且findVal :: [ValPair] -> Int -> Double需要特殊的多态性(参见http://www.haskell.org/haskellwiki/Ad-hoc_polymorphism),这通常是危险的.原因是ad-hoc多态允许使用相同的语法更改语义.
Haskell更喜欢所谓的参数多态.你总是会看到类型签名,你有一个类型变量.
Haskell通过类型类支持更安全的ad-hoc多态性版本.
你有三个选择.
像这样:
findVal :: Num a => [ValPair] -> a -> Double
{-# SPECIALISE findVal :: [ValPair] -> Int -> Double #-}
{-# SPECIALISE findVal :: [ValPair] -> Double -> Double #-}
findVal = ...
Run Code Online (Sandbox Code Playgroud)
Haskell不支持C++样式的重载(好吧它与类型类有关,但我们不以同样的方式使用它们).是的,有一些龙与添加它有关,主要与类型推断有关(变成指数时间或不可判断的或类似的东西).但是,在Haskell中看到像这样的"方便"代码是非常罕见的.哪一个是一个Int还是一个Double?由于您的Int方法委托给Double方法,我的猜测是Double"正确的".只需使用那个.由于文字重载,您仍然可以将其称为:
findVal whatever 42
Run Code Online (Sandbox Code Playgroud)
而42将被视为一个Double.唯一可以解决的问题是,如果你有一些基本上属于Int 某个地方的东西,你需要将它作为这个参数传递.然后用fromIntegral.但是如果你努力让你的代码到处都使用"正确"的类型,那么这种情况就不常见了(当你必须进行转换时,值得引起注意).