Haskell partial function application with $

徘徊边缘 提交于 2019-12-10 15:49:14

问题


I'm new to Haskell and looking at a simple example of using function application with $.

It seems straightforward - it takes a function and applies it to a value.

So this makes sense:

> (+3) $ 2
5

This also makes sense:

> ($) (+3) 2
5

This makes sense because the first argument is the function, and the second argument is the value.

Now considering using $ to create a partial function.

Looking at types, this makes sense - it just needs a Num type value for b:

> :t ($) (+3)
($) (+3) :: Num b => b -> b

But here's where I get lost - what is happening here?:

> :t ($) (2)
($) (2) :: Num (a -> b) => a -> b

I would have expected the first argument would need to be a function, not a simple Num value.

So here's my questions:

  1. What's happening here?
  2. What does the constraint Num (a -> b) syntax mean?
  3. What's an example of using ($) in this way, that starts with something like ($) (2)?

Thanks!


回答1:


On the one hand, numeric literals like 2 are actually read as fromInteger 2 :: Num a => a so can denote any value of type Num a => a, meaning, any type which is in type class Num, i.e. has among other things a special version of fromInteger defined which returns the actual value of the actual type, converted from the integer 2:

> :i Num
class Num a where
  (+) :: a -> a -> a
  (*) :: a -> a -> a
  (-) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a

As the Haskell Tutorial puts it (in 10.3),

An integer numeral (without a decimal point) is actually equivalent to an application of fromInteger to the value of the numeral as an Integer.

On the other hand, ($) has the type

> :t ($)
($) :: (a -> b) -> a -> b

So we have

fromInteger 2 :: Num a1 =>   a1
($)           ::          (a -> b) -> a -> b
--------------------------------------------
($) 2         :: Num      (a -> b) => a -> b

So it's a function, which must also be in the type class Num.

Normally that's not the case but Haskell doesn't know if you could be importing some module which does define such an instance:

instance Num (a -> b) where
   ....
   fromInteger n = ....
   ....

so it allows this possibility at the type checking, and only then, seeing that there is no such actual instance defined anywhere, it errors out on that.

For example, following the hint from @augustss in the comments,

instance (Num b) => Num (a -> b) where
   (+) f g x = f x + g x
   (*) f g x = f x * g x
   abs f x = abs (f x)
   negate f x = negate (f x)
   signum f x = signum (f x)
   fromInteger n = const (fromInteger n)

lets us write (sin + 2 * cos^2) x.



来源:https://stackoverflow.com/questions/54491190/haskell-partial-function-application-with

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!