为什么类型参数不能是什么?

Tri*_*Gao 1 haskell

在我看来,type参数a可以是包括列表在内的任何东西.为什么这不行?

fun :: a -> a
fun [] = []
Run Code Online (Sandbox Code Playgroud)

Haskell不想编译这段代码.我想知道为什么.

Couldn't match expected type `a' with actual type `[t0]'
 `a' is a rigid type variable bound by
    the type signature for fun :: a -> a
Run Code Online (Sandbox Code Playgroud)

我可以让它像这样重写签名

fun :: [a] -> [a]
Run Code Online (Sandbox Code Playgroud)

但这不是我想要的东西,因为我想保持函数的多态性.我想知道如何id在空列表上工作.

Prelude> :t id
id :: a -> a
Prelude> id []
[]
Run Code Online (Sandbox Code Playgroud)

Dan*_*zer 7

类型变量可以是任何东西,但是你(被调用者)不能选择什么.

让我们绕道一些术语.Haskell默认为所谓的"通用量化".这意味着所有实例化可以满足给定的类型变量.呼叫者可以用他们想要的任何东西填充它.

所以当你说

fun :: forall a. a -> a
fun [] = []
Run Code Online (Sandbox Code Playgroud)

就像说,"对于每种可能的类型a,把它当作一个列表",这显然是无稽之谈!

听起来你想要更像adhoc多态的东西,我们使用类型类

{-# LANGUAGE OverlappingInstances, FlexibleInstances #-}
class Id a where
  myId :: a -> a
instance Id a where
  myId = id
instance Id [a] where
  myId [] = [ undefined ] -- special case
  myId xs = xs
Run Code Online (Sandbox Code Playgroud)