我可以在Haskell中创建自己的函数组合运算符吗?

我可以在Haskell中创建自己的函数组合运算符吗?,haskell,functional-programming,Haskell,Functional Programming,Haskell中的函数组合运算符定义为: (.) :: (b -> c) -> (a -> b) -> a -> c 当我尝试在Haskell中创建自己的函数组合操作符时,o,它不起作用,我做错了什么 o :: a -> (a -> b) -> (b -> c) -> c g :: Double -> String g x = show x h :: Int -> Double h x = fromIntegral

Haskell中的函数组合运算符定义为:

(.) :: (b -> c) -> (a -> b) -> a -> c
当我尝试在Haskell中创建自己的函数组合操作符时,
o
,它不起作用,我做错了什么

o :: a -> (a -> b) -> (b -> c) -> c

g :: Double -> String
g x = show x 

h :: Int -> Double
h x = fromIntegral x

f :: Int -> String
f x = o x h g       -- can it also be written like this: f = o h g 
错误消息:

C:\Users\August\Desktop\Haskell\Template\Ex.hs:36:1: error:
    The type signature for `o' lacks an accompanying binding
Failed, modules loaded: none.

您的函数
o
非常类似于函数组合

(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
o = (flip .) . flip . (flip .) $ (.)
您可以重写
的定义,只需稍微重新排列参数:

o :: a -> (a -> b) -> (b -> c) -> c
o x f g = g (f x)
或者,您可以尝试创建
o
,方法是在
的参数周围来回移动:

(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
o = (flip .) . flip . (flip .) $ (.)
在这个定义中,我们使用
flip
交换
(.)
的第一个和第二个参数,使用
(flip.)
交换第二个和第三个参数。对于函数
a->b->c->d
,它将为我们提供:

a -> b -> c -> d
-- swap b and c with (flip .)
a -> c -> b -> ->d
-- swap a and c with (.)
c -> a -> b -> -> d
-- swap a and b
c -> b -> a -> d with (flip .)
如果您想知道为什么
(翻转)
交换第二个和第三个参数,我建议您阅读和。它归结为
确保
翻转
应用于传递给
(翻转)
的任何函数的结果,并且交换函数结果的第一个和第二个参数与交换其第二个和第三个参数相同


不过,老实说,我认为没有必要使用
o
函数,因为您可以将
f
重写为:

 f :: Int -> String
 f x = g . h $ x
甚至

f = g . h

您的函数
o
非常类似于函数组合

(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
o = (flip .) . flip . (flip .) $ (.)
您可以重写
的定义,只需稍微重新排列参数:

o :: a -> (a -> b) -> (b -> c) -> c
o x f g = g (f x)
或者,您可以尝试创建
o
,方法是在
的参数周围来回移动:

(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
o = (flip .) . flip . (flip .) $ (.)
在这个定义中,我们使用
flip
交换
(.)
的第一个和第二个参数,使用
(flip.)
交换第二个和第三个参数。对于函数
a->b->c->d
,它将为我们提供:

a -> b -> c -> d
-- swap b and c with (flip .)
a -> c -> b -> ->d
-- swap a and c with (.)
c -> a -> b -> -> d
-- swap a and b
c -> b -> a -> d with (flip .)
如果您想知道为什么
(翻转)
交换第二个和第三个参数,我建议您阅读和。它归结为
确保
翻转
应用于传递给
(翻转)
的任何函数的结果,并且交换函数结果的第一个和第二个参数与交换其第二个和第三个参数相同


不过,老实说,我认为没有必要使用
o
函数,因为您可以将
f
重写为:

 f :: Int -> String
 f x = g . h $ x
甚至

f = g . h

它不起作用的原因正是错误消息所说的:您为
o
编写了类型签名,但没有编写定义,例如
o x f g=g(f x)
。它不起作用的确切原因是错误消息说:您为
o
编写了类型签名,但没有编写定义,例如
o x f g=g(f x)