重载函数签名haskell

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在调用站点使用.当涉及实际上不同的行为或逻辑而不是混杂时,通常需要类型类.

  • sclv有点说:"当涉及到实际上不同的行为或逻辑时,你通常需要类型类,而不是混乱." (7认同)
  • 当然,它有效,但在这种情况下不是惯用的解决方案.`CanFindVal`不是一个非常有意义的类型类.-1 (3认同)

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多态性版本.

你有三个选择.

  1. 使用显式函数名称继续您正在执行的操作.这是合理的,它甚至被一些c库使用,例如opengl.
  2. 使用自定义类型.这可能是最好的方式,但是很重,需要相当数量的代码(通过haskells非常紧凑的标准).看看sclv的代码答案.
  3. 尝试使用现有的类型类(如果使用GHC)获得专业化的性能.

像这样:

findVal :: Num a => [ValPair] -> a -> Double
{-# SPECIALISE findVal :: [ValPair] -> Int -> Double #-}
{-# SPECIALISE findVal :: [ValPair] -> Double -> Double #-}
findVal = ...
Run Code Online (Sandbox Code Playgroud)


luq*_*qui 6

Haskell不支持C++样式的重载(好吧它与类型类有关,但我们不以同样的方式使用它们).是的,有一些龙与添加它有关,主要与类型推断有关(变成指数时间或不可判断的或类似的东西).但是,在Haskell中看到像这样的"方便"代码是非常罕见的.哪一个是一个Int还是一个Double?由于您的Int方法委托给Double方法,我的猜测是Double"正确的".只需使用那个.由于文字重载,您仍然可以将其称为:

findVal whatever 42
Run Code Online (Sandbox Code Playgroud)

42将被视为一个Double.唯一可以解决的问题是,如果你有一些基本上属于Int 某个地方的东西,你需要将它作为这个参数传递.然后用fromIntegral.但是如果你努力让你的代码到处都使用"正确"的类型,那么这种情况就不常见了(当你必须进行转换时,值得引起注意).