Haskell 两者的区别是什么。(点)和$(美元符号)?
点Haskell 两者的区别是什么。(点)和$(美元符号)?,haskell,syntax,function-composition,Haskell,Syntax,Function Composition,点()和美元符号($)之间有什么区别 据我所知,它们都是语法上的甜点,不需要使用括号。它们有不同的类型和不同的定义: infixr 9 . (.) :: (b -> c) -> (a -> b) -> (a -> c) (f . g) x = f (g x) infixr 0 $ ($) :: (a -> b) -> a -> b f $ x = f x ($)旨在取代普通函数应用程序,但优先级不同,以帮助避免使用括号()用于将两个函数组合在一
()
和美元符号($)
之间有什么区别
据我所知,它们都是语法上的甜点,不需要使用括号。它们有不同的类型和不同的定义:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x
($)
旨在取代普通函数应用程序,但优先级不同,以帮助避免使用括号()
用于将两个函数组合在一起以生成一个新函数
在某些情况下,它们是可互换的,但一般情况下并非如此。它们所在的典型示例是:
f $ g $ h $ x
==>
换句话说,在一系列的
$
中,除了最后一个之外,所有的都可以被
替换。它们有不同的类型和不同的定义:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x
($)
旨在取代普通函数应用程序,但优先级不同,以帮助避免使用括号()
用于将两个函数组合在一起以生成一个新函数
在某些情况下,它们是可互换的,但一般情况下并非如此。它们所在的典型示例是:
f $ g $ h $ x
==>
换句话说,在一系列的$
中,除了最后一个之外,所有的都可以被
替换。还请注意,($)
是专门用于函数类型的标识函数。标识函数如下所示:
id :: a -> a
id x = x
($) :: (a -> b) -> (a -> b)
($) = id
(putStrLn . show) (1 + 1)
而($)
看起来是这样的:
id :: a -> a
id x = x
($) :: (a -> b) -> (a -> b)
($) = id
(putStrLn . show) (1 + 1)
注意,我特意在类型签名中添加了额外的括号
($)
的使用通常可以通过添加括号来消除(除非在节中使用运算符)。例如:f$gx
变成f(gx)
()
的使用通常更难替换;它们通常需要lambda或引入显式函数参数。例如:
f = g . h
变成
f x = (g . h) x
f x = g (h x)
变成
f x = (g . h) x
f x = g (h x)
希望这有帮助 还要注意,($)
是专门针对函数类型的标识函数。标识函数如下所示:
id :: a -> a
id x = x
($) :: (a -> b) -> (a -> b)
($) = id
(putStrLn . show) (1 + 1)
而($)
看起来是这样的:
id :: a -> a
id x = x
($) :: (a -> b) -> (a -> b)
($) = id
(putStrLn . show) (1 + 1)
注意,我特意在类型签名中添加了额外的括号
($)
的使用通常可以通过添加括号来消除(除非在节中使用运算符)。例如:f$gx
变成f(gx)
()
的使用通常更难替换;它们通常需要lambda或引入显式函数参数。例如:
f = g . h
变成
f x = (g . h) x
f x = g (h x)
变成
f x = (g . h) x
f x = g (h x)
希望这有帮助 短而甜的版本:
调用作为其左参数的函数和作为其右参数的值($)
在作为其右参数的函数上构成作为其左参数的函数()
调用作为其左参数的函数和作为其右参数的值($)
在作为其右参数的函数上构成作为其左参数的函数()
- 短而甜的版本:
putStrLn (show (1 + 1))
如果要删除这些括号,以下任何一行也可以执行相同的操作:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
运算符的主要目的不是避免使用括号,而是链接函数。它允许您将右侧显示的内容的输出与左侧显示的内容的输入绑定在一起。这通常也会减少括号,但效果不同
回到同一个例子:
putStrLn (show (1 + 1))
(1+1)
没有输入,因此不能与
运算符一起使用show
可以获取Int
并返回字符串
putStrLn
可以获取String
并返回IO()
show
链接到putStrLn
:
id :: a -> a
id x = x
($) :: (a -> b) -> (a -> b)
($) = id
(putStrLn . show) (1 + 1)
如果您喜欢的括号太多,请使用$
操作符将其去掉:
putStrLn . show $ 1 + 1
$
运算符用于避免使用括号。之后出现的任何事物都将优先于之前出现的任何事物
例如,假设您有一行内容如下:
putStrLn (show (1 + 1))
如果要删除这些括号,以下任何一行也可以执行相同的操作:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
运算符的主要目的不是避免使用括号,而是链接函数。它允许您将右侧显示的内容的输出与左侧显示的内容的输入绑定在一起。这通常也会减少括号,但效果不同
回到同一个例子:
putStrLn (show (1 + 1))
(1+1)
没有输入,因此不能与
运算符一起使用show
可以获取Int
并返回字符串
putStrLn
可以获取String
并返回IO()
show
链接到putStrLn
:
id :: a -> a
id x = x
($) :: (a -> b) -> (a -> b)
($) = id
(putStrLn . show) (1 + 1)
如果您喜欢的括号太多,请使用$
操作符将其去掉:
putStrLn . show $ 1 + 1
($)
允许将函数链接在一起,而无需添加括号来控制求值顺序:
Prelude> head (tail "asdf")
's'
Prelude> head $ tail "asdf"
's'
compose操作符(.)
在不指定参数的情况下创建新函数:
Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'
Prelude> let second = head . tail
Prelude> second "asdf"
's'
上面的例子可以说是说明性的,但并没有真正显示使用组合的便利性。还有一个类比:
Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"
如果我们只使用第三个,我们可以通过使用lambda来避免命名它:
Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"
最后,合成让我们避免了lambda:
Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"
($)
允许将函数链接到一起