Function Haskell:应用两次翻转(翻转类型)
我正在学习Haskell的一些基本函数。我用Flip做了一些练习,它接受两个参数的函数,并根据参数的顺序计算结果。考虑函数<强>翻转翻转< /强>,我会想到,按照翻转的定义,它翻转了两次参数,用原始顺序中的参数来评估原始函数。当我用ghci检查函数类型来检查这个假设时,它产生了: 翻转:b->(a->b->c)->a->cFunction Haskell:应用两次翻转(翻转类型),function,haskell,functional-programming,Function,Haskell,Functional Programming,我正在学习Haskell的一些基本函数。我用Flip做了一些练习,它接受两个参数的函数,并根据参数的顺序计算结果。考虑函数翻转翻转< /强>,我会想到,按照翻转的定义,它翻转了两次参数,用原始顺序中的参数来评估原始函数。当我用ghci检查函数类型来检查这个假设时,它产生了: 翻转:b->(a->b->c)->a->c 我不明白为什么这是flip的功能类型。它接受参数b和参数(a->b->c)并生成函数a->c。为什么会这样?我真的很想得到一个解释,因为我对此一无所知。提前感谢翻动两次将是\f->
我不明白为什么这是flip的功能类型。它接受参数b和参数(a->b->c)并生成函数a->c。为什么会这样?我真的很想得到一个解释,因为我对此一无所知。提前感谢翻动两次将是
\f->flip(flip f)
,或flip。翻转
。这确实会有类型(a->b->c)->(a->b->c)
您在这里所做的是在flip
函数上应用flip
,即翻转flip
的参数顺序。所以如果我们从
flip :: (a -> b -> c) -> b -> a -> c
-- and, as the type of the argument
flip :: (a' -> b' -> c') -> b' -> a' -> c'
那么如果我们匹配类型
a = (a' -> b' -> c')
b = b'
c = a' -> c'
我们得到了结果
flip flip :: b' -> (a' -> b' -> c') -> (a' -> c')
您不会两次应用翻转
功能。如果要应用两次翻转
,请查找:
flip . flip :: (b -> a -> c) -> b -> a -> c
由于flip2
是flip1
的参数,因此这意味着flip2
的类型与flip1
的参数类型相同,因此这意味着:
a -> (b -> c )
~ (d -> e -> f) -> (e -> (d -> f))
flip1 flip2 :: b -> a -> c
flip1 flip2 :: e -> (d -> e -> f) -> (d -> e)
因此,这意味着a~(d->e->f)
(类型a
与d->e->f
)相同,b~e
和c~(d->e)
。因此,函数flip1 flip2
的类型是flip1
的输出类型,但具有等效性,因此这意味着:
a -> (b -> c )
~ (d -> e -> f) -> (e -> (d -> f))
flip1 flip2 :: b -> a -> c
flip1 flip2 :: e -> (d -> e -> f) -> (d -> e)
让我们看看这些类型:
flip :: (a -> b -> c) -> b -> (a -> c)
flip :: (d -> e -> f ) -> e -> d -> f
flip flip :: b -> (a -> b -> c) -> (a -> c)
换句话说,flip
反转其参数的前两个参数,flip
的前两个参数是要翻转的函数和该函数的第二个参数。因此,当您翻转它时,顺序将变成“第二个参数”、“函数”、“第一个参数”,而不是按“函数”、“第二个参数”、“第一个参数”的顺序取参数
如果要翻转,然后再翻转,请执行以下操作:
doubleflip x = flip (flip x)
或相当于:
doubleflip = flip . flip
()
操作符将右侧的输出输入到左侧。如果不翻转两次,可以翻转翻转
功能。为了好玩,请尝试一下翻转
。谢谢您简洁的回答。我意识到我还没有完全明白一件事(很抱歉,如果这个问题听起来很琐碎,但我对Haskell是完全陌生的)。为什么要匹配“b=b'”而不是“b=(b'->a')”然后再匹配“c=c'”?为什么第一个关联是有效的,而不是我给出的另一个?因为->
语法具有正确的关联性。明确地说,类型是((a->(b->(c)))->(b->(a->(c)))
。Haskell中的所有函数实际上都是一元函数(只接受一个参数),它们可能会返回另一个再次接受另一个参数的函数。类型(b'->(a'->c')
不同于((b'->a')->c')
,它们只是不匹配。