代码之家  ›  专栏  ›  技术社区  ›  Long

Haskell的类型系统将数值视为函数?

  •  6
  • Long  · 技术社区  · 15 年前

    Prelude Data.Maclaurin> :t ((+) . ($) . (+))
    ((+) . ($) . (+)) :: (Num a) => a -> (a -> a) -> a -> a
    

    (Data.Maclaurin是通过包向量空间导出的。)所以它需要一个Num、一个函数、另一个Num并最终返回一个Num。下面的工作是什么魔法?

    Prelude Data.Maclaurin> ((+) . ($) . (+)) 1 2 3
    6
    

    2显然不是一个函数(a->a) 还是我错过了什么?

    2 回复  |  直到 14 年前
        1
  •  16
  •   sth    15 年前

    这个 Data.NumInstances 同一包的模块 defines A. Num 返回数字的函数的实例:

    instance Num b => Num (a->b) where
      (+)         = liftA2 (+)
      (*)         = liftA2 (*)
      fromInteger = pure . fromInteger
      ...
    

    在Haskell中是一个整数,比如 2 是泛型的,因此它可以表示

    Prelude> :t 2
    2 :: (Num t) => t
    

    要将其转换为特定上下文中所需类型的实际数字, fromInteger 号码

    因为上面提到的helper模块定义了 号码 对于函数, fromInteger 2 获取问题中构造的第二个参数所需的函数。整个表达式的计算结果恰好是 6

        2
  •  1
  •   Charles Duffy    15 年前

    你有充分的理由感到困惑。使用 Data.NumInstances GHC中的模块(由 Data.Maclaurin )可以强制 Num

    Prelude Data.NumInstances> :t (2 :: (Num a) => a -> a)
    (2 :: (Num a) => a -> a) :: (Num a) => a -> a
    Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 0          
    2
    Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 1000
    2
    

    对表达式的求值本质上是,

    ((+) . ($) . (+)) 1 2 3 = ((+) . ($) . (1+)) 2 3
                            = ((+) (1+)) 2 3
                            -- (+) is defined for functions that return a Num
                            = ((+) (1+) (\_ -> 2)) 3  
                            = ((+2) . (1+)) 3
                            = 6