在我看来,类型参数a
可以是包括列表在内的任何内容。为什么这不起作用?
fun :: a -> a
fun [] = []
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
我可以让它像这样重写签名
fun :: [a] -> [a]
但这不是我想要的东西,因为我想保持函数的多态性。
我想知道id
如何在空列表上工作。
Prelude> :t id
id :: a -> a
Prelude> id []
[]
答案 0 :(得分:7)
类型变量可以可以是任何东西,但是你(被调用者)无法选择什么。
让我们绕道一些术语。 Haskell默认为所谓的“通用量化”。这意味着所有实例化可以满足给定的类型变量。呼叫者可以随意填写它。
所以当你说
时fun :: forall a. a -> a
fun [] = []
就像说,“对于每种可能的类型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
答案 1 :(得分:0)
让我们思考,它可能是写的(它不是,但为了好玩):
fun :: a -> a
fun [] = []
这意味着通过模式匹配,
fun _ = error "Nonwritten error!"
这意味着接下来的两件事:
1)存在额外数据类型,如:
data Universe = forall a. a
但是这个数据在Haskell中不存在!我们这里没有数据构造函数
2)这意味着你签名不对:
fun :: Universe -> Universe