Haskell 为什么是a->;b->;c函数参数可以接受a->;a型?
这将成功编译:Haskell 为什么是a->;b->;c函数参数可以接受a->;a型?,haskell,Haskell,这将成功编译: test = f id f :: (a -> b -> c) -> String f g = "test" id的类型为a->a,但f的第一个参数的类型为(a->b->c) 我认为它不应该编译。我无法理解它。因为您可以绑定未实例化的变量f::(a->b->c)->String表示,对于任意3种类型的a、b和c,f从a到b到c取一个函数并返回String 重要的是要记住,f:(a->b->c)->String与f:(a->(b->c))->
test = f id
f :: (a -> b -> c) -> String
f g = "test"
id
的类型为a->a
,但f
的第一个参数的类型为(a->b->c)
我认为它不应该编译。我无法理解它。因为您可以绑定未实例化的变量
f::(a->b->c)->String
表示,对于任意3种类型的a、b和c,f从a到b到c取一个函数并返回String
重要的是要记住,f:(a->b->c)->String
与f:(a->(b->c))->String
是等价的,因为使用了curry
id
接受任何类型,并返回该类型
所以如果我们把它换成,
id
返回b->c
,然后取a
,那么如果a
可以是b->c
,它可以是任何类型的,那么这很好。短版本:它工作的原因是id
可以接受并返回函数,因此它的行为就好像它是一个双参数函数一样。现在来看长版本
id
是一个函数,它接受一个值并返回不变的值。因为它非常简单,所以它可以对各种不同的值--Int
s和Bool
s和String
s以及列表和树
id :: Int -> Int
id :: Bool -> Bool
id :: String -> String
id :: [(b, c)] -> [(b, c)]
id :: Tree b -> Tree b
id :: (b -> c) -> (b -> c)
…和功能,为什么不呢
f
是一个接受两个参数函数并忽略它们的函数。因为它对你给它的函数的处理非常简单,它可以对各种不同的两个参数函数——加法、串联、配对、忽略、打印
f :: (Int -> Int -> Int) -> String
f :: ([b] -> [b] -> [b]) -> String
f :: (b -> c -> (b, c)) -> String
f :: (b -> c -> b) -> String
f :: (Handle -> String -> IO ()) -> String
f :: ((b -> c) -> b -> c) -> String
…以及接受函数和参数并将其应用于另一个的操作,为什么不呢
但是两个参数函数实际上只是一个参数函数,它们本身返回一个函数。因此,这两种类型实际上只是同一类型的不同拼写:
事实证明,我对这两种类型给出的两种行为描述也是一样的。回想起来,它们是:
id :: a -> a
f :: (a -> b -> c) -> String
并通过为两者选择a~b->c
使它们组合在一起。(这只是巧合,a
的两个实例化属于同一类型——进行统一时通常不是这样!)在两个类型签名中实例化a
到b->c
后,我们得到:
id :: (b -> c) -> b -> c
f :: ((b -> c) -> b -> c) -> String
提示:表达式
id not
中id
的类型是什么?我不明白你的意思~~我的意思是,表达式id“hi there”
中id
的类型是String->String
,因为“hi there”
有类型String,所以a
被实例化为。not
的类型是Bool->Bool
。那么表达式id not
中id
的类型是什么?a
也可以是一种类型,a->a
中的a
与a->b->c
中的a
不同a->b->c
是a->(b->c)
的缩写,因此如果你传递id::d->d
,那么我们知道a~d~b->c
@user754458:如果我想让GHCi回答一个问题,比如“在表达式id not
”中,id的类型是什么,我可能会将其表述为:type\(\U::What)->(id::What)不是
。由于what
在这里是一个新的类型变量,它不会匹配任何具体类型,因此编译器将报告一个类型错误,说明what
与我注释的子表达式的推断类型不匹配,并将在错误消息中为我打印该类型。这将使用“作用域类型变量”语言标志(:set-XScopedTypeVariables
)。@user754458为什么不使用?这就是重点。在f实例中,通过传递它的id,您可以向您喜欢的类型添加任何限制,因此您可以将a限制为b->c@user754458为了匹配类型,编译器求解方程a->b->c=x->x
,并发现x=a=(b->c)
。次要术语注意:这里没有自由(类型)变量。绑定是隐式的,但是语言规范明确了在没有绑定时如何插入绑定。显式版本,id::forall a。a->a
和f::对于所有a b c。(a->b->c)->字符串
,问题中的签名是简写的,这使得所有变量都不是自由变量更加明显。@user1937198否,自由和未绑定的含义相同。更符合文献的措辞应该是“因为你可以实例化变量”。我想不出任何相关的、正确的形容词附加到“变量”上。@DanielWagner如果措辞可以实例化,那么可以实例化还是不实例化?非常感谢。回答得好!
id :: (b -> c) -> b -> c
f :: ((b -> c) -> b -> c) -> String