对成对中不同类型的元素应用同态

问题描述 投票:0回答:1

简而言之,我希望在 Haskell 中进行以下类型检查:

both f (x, y) = (f x, f y)

foo :: ([Int], [Char])
foo = ([1], "a")

bar :: ([Int], [Char])
bar = both (concat . replicate 3) foo  -- intended: ([1, 1, 1], "aaa")

我收到的错误是:

• Couldn't match type ‘Char’ with ‘Int’
  Expected: ([Int], [Int])
    Actual: ([Int], [Char])
• In the second argument of ‘both’, namely ‘foo’
  In the expression: both (concat . replicate 3) foo
  In an equation for ‘bar’: bar = both (concat . replicate 3) foo

在将以下类型注释添加到

both
后,我就可以编译它了:

both :: (forall x. [x] -> [x]) -> ([a], [b]) -> ([a], [b])
both f (x, y) = (f x, f y)

但是这个解决方案感觉并不完全令人满意,因为

both
看起来更通用,因此,例如
both id (1, "a")
也被接受。我可以从这里走得更远吗?

haskell functional-programming
1个回答
0
投票

我认为这是最明智的版本:

both :: ∀ t a b . (∀ x . t x -> t x) -> (t a, t b) -> (t a, t b)
both f (x,y) = (f x, f y)

您的列表示例是

t ~ []
的特殊情况,但它也可以与其他容器一起使用,也可以间接与“不包含”值一起使用,因为您始终可以使用
Identity
– 尽管这基本上是无用,因为唯一的功能
∀ x . x -> x
id

© www.soinside.com 2019 - 2024. All rights reserved.