如何在Haskell中计算(。)(。)的类型? 我知道它应该是
(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
但如何在没有电脑的情况下计算它?
答案 0 :(得分:8)
(.) :: (b -> c ) -> ((a -> b) -> (a -> c))
(.) :: ((e -> f) -> ((d -> e) -> (d -> f)))
(.)(.) :: ((a -> (e -> f)) -> (a -> ((d -> e) -> (d -> f))))
(.)(.) :: (a -> (e -> f)) -> (a -> ((d -> e) -> (d -> f)))
(.)(.) :: (a -> e -> f) -> a -> ((d -> e) -> (d -> f))
(.)(.) :: (a -> e -> f) -> a -> (d -> e) -> (d -> f)
(.)(.) :: (a -> e -> f) -> a -> (d -> e) -> d -> f
答案 1 :(得分:5)
(.)
的类型为(b -> c) -> ((a -> b) -> a -> c
),因此第一个参数的类型应为b -> c
。
现在,如果我们再次使用它,我们必须将b
替换为b' -> c'
,将c
替换为(a' -> b') -> a' -> c')
(第二个(.)
应该具有类型(b' -> c') -> ((a' -> b') -> a' -> c')
)我们得到了
(a -> b' -> c') -> a -> (a' -> b') -> a' -> c'
(重命名后)与上述相同。
请注意,我在这里使用了a -> b -> c = a -> (b -> c)
是的,我知道 - 你想手工制作 - 但 GHCi 是一个非常有价值的工具,你真的应该用它来确认你的体力劳动。
来自终端:
$ ghci
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Prelude> :t (.)(.)
(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
Prelude>
您可以看到类型为(a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
btw::t
是:type
的缩写,你可以在GHCi会话中看到:help
的所有命令。
答案 2 :(得分:0)
由于我对接受的答案中缺少的解释不是特别满意,我也给了我的POV:
-- this is the original type signature
(.) :: (b -> c) -> (a -> b) -> a -> c
-- now because of haskell polymorphism,
-- even 'b' and 'c' and so on could be functions
--
-- (.)(.) means we shove the second function composition
-- into the first as an argument.
-- Let's give the second function a distinct type signature, so we
-- don't mix up the types:
(.) :: (e -> f) -> (d -> e) -> d -> f
-- Since the first argument of the initial (.) is of type (b -> c)
-- we could say the following if we apply the second (.) to it:
(b -> c) == (e -> f) -> (d -> e) -> d -> f
-- further, because of how currying works, as in
(e -> f) -> (d -> e) -> d -> f == (e -> f) -> ((d -> e) -> d -> f)
-- we can conclude
b == (e -> f)
c == (d -> e) -> d -> f
-- since we passed one argument in, the function arity changes,
-- so we'd actually only have (a -> b) -> a -> c left, but that
-- doesn't represent the types we have now, so we have to substitute
-- for b and c, so
(a -> b) -> a -> c
-- becomes
(.)(.) :: (a -> (e -> f)) -> a -> (d -> e) -> d -> f
-- and again because of currying we can also write
(.)(.) :: (a -> e -> f) -> a -> (d -> e) -> d -> f