Haskell 两个函数的组合类型是什么?例如(flip.const)

Haskell 两个函数的组合类型是什么?例如(flip.const),haskell,types,type-inference,ghci,strong-typing,Haskell,Types,Type Inference,Ghci,Strong Typing,我已经开始学习Haskell,我很好奇如何找到函数的组合类型:例如: :t flip flip :: (a -> b -> c) -> b -> a -> c :t const const :: a -> b -> a 如何手动执行:t(flip.const) 当然,GHCi可以帮助您: :t (flip.const) (flip . const) :: (b -> c) -> b -> a -> c 但是你自己怎么做呢?这

我已经开始学习Haskell,我很好奇如何找到函数的组合类型:例如:

:t flip
flip :: (a -> b -> c) -> b -> a -> c

:t const
const :: a -> b -> a
如何手动执行
:t(flip.const)

当然,GHCi可以帮助您:

:t (flip.const)
(flip . const) :: (b -> c) -> b -> a -> c

但是你自己怎么做呢?

这里有三个功能:

  • )
  • );及
  • 请注意,如果将
    (.)
    函数用作运算符,则实际上已编写:

    (.) flip const
    
    或者更详细:

    ((.) flip) const
    
    现在,让我们首先以详细的方式编写函数的签名,并使用不同的可变名称,以便这些签名不会冲突:

    (.) :: (b -> c) -> ((a -> b) -> (a -> c))
    flip :: (d -> (e -> f)) -> (e -> (d -> f))
    const :: g -> (h -> g)
    
    因此,我们将
    ()
    应用于
    flip
    ,这意味着我们必须将类型为
    (b->c)
    ()
    的参数与flip的签名相匹配,因此我们通过以下方式解决此问题:

    b               -> c
    (d -> (e -> f)) -> (e -> (d -> f))
    
    这是唯一可能的匹配(请注意括号)。这意味着:

    b ~ (d -> (e -> f))
    c ~ (e -> (d -> f))
    
    (此处
    a~b
    表示
    a
    b
    是同一类型)

    因此,
    (.)flip
    的类型为

    (.) flip :: (a -> b) -> (a -> c)
    
    这也是一个带有一个参数的函数(Haskell中的所有函数都有一个参数),该参数的类型为
    a->b
    。 我们将该函数应用于
    常量
    ,因此我们再次进行模式匹配:

    a -> b
    g -> (h -> g)
    
    这意味着
    a~g
    b~(d->(e->f))~(h->g
    ,因此我们知道
    d~h
    g~(e->f)

    我们知道
    (.)flip)const
    的类型为:

    ((.) flip) const :: a -> c`
    
    所以现在是用
    a
    代替
    g
    g~(e->f)
    ,所以
    a~(e->f)
    。此外,我们知道
    c~(e->(d->f))
    ,这意味着类型为:

    ((.) flip) const :: (e -> f) -> (e -> (d -> f))
    
    或者以不太详细的形式:

    flip . const :: (e -> f) -> e -> d -> f
    

    除了变量重命名外,它与GHCi派生的类型相同。

    这里有三个功能:

  • )
  • );及
  • 请注意,如果将
    (.)
    函数用作运算符,则实际上已编写:

    (.) flip const
    
    或者更详细:

    ((.) flip) const
    
    现在,让我们首先以详细的方式编写函数的签名,并使用不同的可变名称,以便这些签名不会冲突:

    (.) :: (b -> c) -> ((a -> b) -> (a -> c))
    flip :: (d -> (e -> f)) -> (e -> (d -> f))
    const :: g -> (h -> g)
    
    因此,我们将
    ()
    应用于
    flip
    ,这意味着我们必须将类型为
    (b->c)
    ()
    的参数与flip的签名相匹配,因此我们通过以下方式解决此问题:

    b               -> c
    (d -> (e -> f)) -> (e -> (d -> f))
    
    这是唯一可能的匹配(请注意括号)。这意味着:

    b ~ (d -> (e -> f))
    c ~ (e -> (d -> f))
    
    (此处
    a~b
    表示
    a
    b
    是同一类型)

    因此,
    (.)flip
    的类型为

    (.) flip :: (a -> b) -> (a -> c)
    
    这也是一个带有一个参数的函数(Haskell中的所有函数都有一个参数),该参数的类型为
    a->b
    。 我们将该函数应用于
    常量
    ,因此我们再次进行模式匹配:

    a -> b
    g -> (h -> g)
    
    这意味着
    a~g
    b~(d->(e->f))~(h->g
    ,因此我们知道
    d~h
    g~(e->f)

    我们知道
    (.)flip)const
    的类型为:

    ((.) flip) const :: a -> c`
    
    所以现在是用
    a
    代替
    g
    g~(e->f)
    ,所以
    a~(e->f)
    。此外,我们知道
    c~(e->(d->f))
    ,这意味着类型为:

    ((.) flip) const :: (e -> f) -> (e -> (d -> f))
    
    或者以不太详细的形式:

    flip . const :: (e -> f) -> e -> d -> f
    
    除了变量重命名外,它与GHCi派生的类型相同。

    我们还有
    (>>>)=flip(.)
    ,这更容易处理,按类型:

    f . g = g >>> f
    
    g ::       a -> b
    f ::            b -> c
    g >>> f :: a ->      c
    
    因此

    翻转。常数::(b->c)->b->a->c
    。GHCi也这么说

    从这种类型中,我们立即看到
    (flip.const)fxz=fx
    。实际上
    (flip.const)fxz=flip(constf)xz=constfzx=fx

    要从中吸取三个教训:

    • 类型关联到右边,而函数应用程序关联到左边,
      fxyz=(((fx)y)z)
      f::a->(b->(c->d))
    • 垂直对齐的东西有帮助
    • 在不同类型中对类型变量进行编号有助于将它们分开
    我们还有
    (>>>)=flip(.)
    ,更容易处理,按类型:

    f . g = g >>> f
    
    g ::       a -> b
    f ::            b -> c
    g >>> f :: a ->      c
    
    因此

    翻转。常数::(b->c)->b->a->c
    。GHCi也这么说

    从这种类型中,我们立即看到
    (flip.const)fxz=fx
    。实际上
    (flip.const)fxz=flip(constf)xz=constfzx=fx

    要从中吸取三个教训:

    • 类型关联到右边,而函数应用程序关联到左边,
      fxyz=(((fx)y)z)
      f::a->(b->(c->d))
    • 垂直对齐的东西有帮助
    • 在不同类型中对类型变量进行编号有助于将它们分开