【问题标题】:why is this snippet valid with an explicit value, but invalid as a function?为什么这个片段对显式值有效,但作为函数无效?
【发布时间】:2016-05-01 19:01:28
【问题描述】:

我正在尝试解决一个需要计算整数的“小”除数的问题。我只是对所有数字进行暴力破解,直到给定数字的平方根,所以要得到 10 的除数,我会写:

[k|k<-[1...floor(sqrt 10)],rem 10 k<1]

这似乎运作良好。但是只要我把它插入一个函数

f n=[k|k<-[1...floor(sqrt n)],rem n k<1]

实际上调用这个函数,我确实得到了一个错误

f 10

No instance for (Floating t0) arising from a use of `it'
The type variable `t0' is ambiguous
Note: there are several potential instances:
  instance Floating Double -- Defined in `GHC.Float'
  instance Floating Float -- Defined in `GHC.Float'
In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it

据我所知,将结果打印到控制台的实际 print 函数会造成问题,但我无法找出问题所在。它说type 是模棱两可的,但该函数显然只能返回一个整数列表。然后我再次检查了类型,f 的(推断)类型是

f :: (Floating t, Integral t, RealFrac t) => t -> [t]

我可以理解f应该能够接受任何实数值,但是谁能解释为什么return类型应该是Integralint以外的任何东西?

【问题讨论】:

    标签: haskell integer


    【解决方案1】:
    [k|k<-[1...floor(sqrt 10)],rem 10 k<1]
    

    这是可行的,因为第一个 10 与后一个不同 - 要看到这一点,我们需要您的函数的类型签名:

    sqrt :: Floating a => a -> a
    rem :: Integral a => a -> a -> a
    

    所以第一个意味着它适用于具有浮点表示的东西 - 又名 FloatDouble ...,而第二个适用于 IntInteger (bigint)、@ 987654328@(无符号8位整数)...

    所以对于sqrt 10 中的10,编译器说-啊,这是一个浮点数,空问题,而对于rem 10 k 中的10,啊,这是一个类似数字的整数,空问题为好吧。

    但是当你将它们捆绑在一个函数中时 - 你是说 n 必须是一个浮点一个整数,编译器不知道这样的事情 - 抱怨。

    那么我们该怎么做才能解决这个问题(haskell 中的旁注范围由.. 而不是... 表示!)。因此,让我们从一个具体的解决方案开始并对其进行概括。

    f :: Int -> [Int]
    f n = [k|k <- [1..n'],rem n k < 1]
        where n' = floor $ sqrt $ fromIntegral n
    

    必要的部分是将Int 转换为浮点数。但是,如果您将其放入库中,您的所有用户都需要坚持使用Int,这没关系,但远非理想 - 那么我们如何概括(如承诺的那样)?我们使用 GHCi 为我们做到这一点,使用一种我们自己也倾向于懒惰的懒惰语言。

    我们首先注释掉类型签名

    -- f :: Int -> [Int]
    f n = [k|k <- [1..n'],rem n k < 1]
        where n' = floor $ sqrt $ fromIntegral n
    
    
    $> ghci MyLib.hs
    ....
    MyLib > :type f
    f :: Integral a => a -> [a]
    

    然后我们可以将其放入库中,如果有人使用 Word8Integer 也可以。

    另一种解决方案是使用rem (floor n) k &lt; 1 并拥有

     f :: Floating a, Integral b => a -> [b]
    

    作为类型,但这会有点尴尬。

    【讨论】:

    • 再次非常感谢您的详细解释!在某些时候,您将不得不设置一个小费罐,因为您似乎在回答我所有的 haskell 问题=)
    猜你喜欢
    • 2014-10-13
    • 2019-11-01
    • 2019-07-26
    • 2016-09-23
    • 2017-08-31
    • 1970-01-01
    • 2019-12-11
    • 2014-11-04
    相关资源
    最近更新 更多