Haskell 中类型为 a -> b 的函数?

Function with type a -> b in Haskell?

Haskell 中是否有类型为 a -> b 的函数?这意味着,是否可以编写一个 f :: a -> b 的函数?我认为这样的函数不存在,原因如下:假设我们在 f :: a -> b 处找到 f,f 2 会产生什么? b 类型的值,但是 b 是什么,因为 Haskell 无法从我给出的参数中推断(我认为)它?这个对吗?否则,你能给我一个这样的功能的例子吗?

有,我认为,正是一个,但它有点作弊:

> let f _ = undefined
> :t f
f:: t -> t1

之所以存在,是因为 bottom 被认为是每种类型的值。

Barring ⊥ (bottom valueundefined etc.),总是可以的,但永远用不上,确实不可能有这个功能。这是我们从多态类型签名中获得的所谓 free theorems 的最简单实例之一。

您凭直觉解释了为什么这是不可能的,但最终失败了,您走在了正确的轨道上。是的,可以考虑f (5 :: Int)。问题是 而不是 编译器“无法推断” b 会是什么——许多实际函数都是这种情况,例如

fromIntegral :: (Num b, Integral a) => a -> b

很有道理; b 将从使用 fromIntegral x 的环境 中推断出 。例如,我可能会写

average :: [Double] -> Double
average l = sum l / fromIntegral (length l)

在这种情况下,length l :: a 具有固定类型 Int,而 fromIntegral (length l) :: b 必须具有固定类型 Double 才能适应环境,这与大多数其他情况不同具有类型推断的语言,来自环境的信息在此可用基于 Hindley-Milner 的语言。

不,f :: a -> b 的问题在于您可以将 ab 实例化为 任何 荒谬的类型组合,而不仅仅是不同的数字类型。因为 f 是不受约束的多态性,所以它必须能够将 任何类型转换为任何其他类型 .

特别是可以转换成空类型 Void.

evil :: Int -> Void
evil = f

然后我可以

muahar :: Void
muahar = f 0

但是,根据 Void 的构造, 不能 是这种类型的值(除了 ⊥ 之外,你无法在不崩溃或无限循环的情况下进行计算).


需要注意的是,根据某些标准,这并不是计算平均值的好方法。

... but what is b since Haskell cannot infer it from the arguments I gave?

根据上下文,Haskell可以推断出return类型;说:

{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances #-}

class Cast a b where
    cast :: a -> b

instance Cast a a where
    cast = id

instance Cast Int String where
    cast = show

instance Cast Int Double where
    cast = fromIntegral

然后,

cast :: Cast a b => a -> b

如果给出足够的上下文,Haskell 知道要使用哪个函数:

\> let a = 42 :: Int
\> let b = 100.0 :: Double

\> "string: " ++ cast a  -- Int -> String
"string: 42"

\> b * cast a            -- Int -> Double
4200.0

为了实现f :: a -> b,这意味着f必须能够return任何可能的类型。即使是今天不存在但有人可以在十年后定义的类型。如果没有某种反射功能,那显然是不可能的。

嗯..."impossible" 是个大词...正如其他答案指出的那样,不可能排除底部。换句话说,f 永远不会 return 类型为 b 的值。它 可以 抛出异常,或者永远循环。但是(可以说)这些东西都不是真正的 "returning a value".

f1 :: a -> b
f1 = error "f1"

f2 :: a -> b
f2 s = error "f2"

f3 :: a -> b
f3 x = f3 x

这些函数都略有不同,而且它们都编译得很好。而且,当然,它们都是无用的! 所以是的,没有 有用的 类型为 a -> b.[=26 的函数=]

如果要分头发:

  • f1 抛出异常。
  • f1 'x' 抛出异常。
  • f2 是一个看起来很正常的函数。
  • f2 'x' 抛出异常。
  • f3 是一个看起来很正常的函数。
  • f3 'x' 不会抛出异常,但它会永远循环,所以它实际上从来没有 returns 任何东西。

基本上,您看到 returns "any type" 的任何函数都是实际上从未 returns 的函数。我们可以在不寻常的单子中看到这一点。例如:

f4 :: a -> Maybe b

完全有可能实现这个函数而不抛出异常或永远循环。

f4 x = Nothing

同样,我们实际上并不是 return b。我们可以类似地做

f5 :: a -> [b]
f5 x = []

f6 :: a -> Either String b
f6 x = Left "Not here"

f7 :: a -> Parser b
f7 x = fail "Not here"