关于Haskell中的构图的困惑 [英] Confusion regarding composition in Haskell

查看:54
本文介绍了关于Haskell中的构图的困惑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究Haskell的书,我意识到我很难理解函数的组成.在最基本的层次上,我有一个管道的心理模型,该模型接受输入并将结果传递给合成中的下一个函数.对于简单的功能,这非常简单.

I'm working through the Haskell book and I've realized I'm having a hard time understanding function composition. At a very basic level I have a mental model of a pipeline that takes an input and passes it's result to the next function in the composition. For simple functions this is very easy.

我遇到的困难是理解组成函数的结果类型签名是如何形成的.例如,如果我们查看elem的基本定义:

Where I'm having difficulty is understanding how the resulting type signatures of composing the functions come to be. For example, if we look at the base definition of elem:

elem :: (Foldable t, Eq a) => a -> t a -> Bool
elem = any . (==)

>:t (==)
(==) :: Eq a => a -> a -> Bool
>:t any
any :: Foldable t => (a -> Bool) -> t a -> Bool

我看不到结果类型签名是如何发生的.如果为我提供了该功能并要求编写类型签名,那我将无可救药.

I fail to see how the resulting type signature occurs. If I were given the function and asked to write the type signature I'd be hopelessly lost.

以下内容也一样.在遍历"一章中,我们告诉我们traverse只是sequenceAfmap组成的:

The same goes for the following. In the chapter on Traversable we were told that traverse is just sequenceA and fmap composed:

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse f = sequenceA . fmap f

>:t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
>:t sequenceA
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)

我自己理解每个函数的类型签名,但是它们如何结合起来以创建traverse的类型签名?

On their own I understand each functions type signature, but how do they combine to create traverse's type signature?

这里超级迷失了,任何帮助将不胜感激.

Super lost here, any help would be greatly appreciated.

推荐答案

也许仅凭视觉上的对齐方式就可以使您对管道的进展方式有所了解,并帮助您迈向下一个困惑点!

Perhaps merely visually aligning the types will get you part of the way to some intuition about how the pipeline progresses, and help you make progress towards your next point of confusion!

(==)       :: Eq a => a -> (a -> Bool)
any        ::              (a -> Bool) -> (t a -> Bool)
any . (==) :: Eq a => a                -> (t a -> Bool)

要在屏幕上保留下一个,我们将Traversable缩写为T,将Applicative缩写为A.您的问题中还有两个f,一个在计算级别,一个在类型级别.为避免混淆,我将把您的计算级别f重命名为g.因此,如果g :: a -> f b用于某些Applicative f:

To keep the next one on one screen, let's abbreviate Traversable to T and Applicative to A. You also have two fs in your question, one at the computation level and one at the type level. To avoid confusion, I'm going to rename your computation-level f to g instead. So if g :: a -> f b for some Applicative f:

fmap g                   ::  T t       =>               t a -> t (f b)
sequenceA                :: (T t, A f) =>                      t (f b) -> f (t b)
sequenceA . fmap g       :: (T t, A f) =>               t a            -> f (t b)
\g -> sequenceA . fmap g :: (T t, A f) => (a -> f b) -> t a            -> f (t b)

(等等!对于fmap g,为什么t的约束是Traversable而不是Functor?好的,没问题:我们实际上可以给它一个更宽松的类型fmap g :: Functor t => .... Traversable必须为Functor,也可以使用这种类型,以使并行性更加清晰.)

(Wait! How come for fmap g, the constraint on t is Traversable and not Functor? Okay, no problem: we can actually give it the more relaxed type fmap g :: Functor t => .... But since every Traversable must be a Functor, it can also be given this type which makes the parallels more clear.)

这篇关于关于Haskell中的构图的困惑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆