在我看来,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)
类型变量可以是任何东西,但是你(被调用者)不能选择什么.
让我们绕道一些术语.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)