是否可以使用一般函数来获取元组中元组的第二个元素?

Min*_*sta 3 haskell types nested tuples function

有人在做一个关于将函数应用两次的函数的练习时问我这个问题,我觉得它很有趣.

我们的想法是我们应该使函数两次,它接受一个函数和一个输入,并将函数应用两次,例如

twice :: (a -> a) -> a -> a
twice f x = f ( f x )
Run Code Online (Sandbox Code Playgroud)

打字通常很有意义.不幸的是,对于元组中的元组和函数fst我们可能认为可以使用它,((1,2),3)但由于类型的原因,这是不可能的twice.

有没有办法让这样的东西有效?

chi*_*chi 7

由于您的输入f = fst是多态的,并且两个调用隐式涉及不同的类型,因此无法进行输入.如果我们将调用显式化,它们将变为:

 fst @ (Int,Int) (fst @ ((Int,Int),Int) ((1,2),3))
Run Code Online (Sandbox Code Playgroud)

可以使用不同的类型twice,要求参数必须是多态函数.这需要Rank2Types:

twice' :: (forall a b . (a, b) -> a) -> ((a,b),c) -> a
twice' f x = f ( f x )
Run Code Online (Sandbox Code Playgroud)

但是,上面的函数用途有限,因为唯一有意义的选择ffst- 没有其他类型的终止函数(forall a b . (a, b) -> a).

也应该可以使用类型类,开启一些扩展.

class C a where
   type Res a
   theF :: a -> Res a

instance C (a, b) where
   type Res (a, b) = a
   theF = fst

twiceC :: (C a, C (Res a)) => a -> Res (Res a)
twiceC x = theF (theF x)
Run Code Online (Sandbox Code Playgroud)

但是,这里必须在函数中定义函数instance,而不是作为参数传递.