Можно ли использовать общую функцию для получения второго элемента кортежа внутри кортежа? - PullRequest
0 голосов
/ 19 февраля 2019

Кто-то спросил меня об этом во время работы над упражнением о функции, применяющей функцию дважды к чему-либо, и я подумал, что это интересно.

Идея состоит в том, что мы должны сделать функцию дважды, которая получает функцию и вход для нее и применяет функцию дважды, например,

twice :: (a -> a) -> a -> a
twice f x = f ( f x )

В целом, типизация имеет смысл.К сожалению, для случая кортежей в кортежах и функции fst мы могли бы подумать, что можно использовать ее на ((1,2),3), но это невозможно из-за типа twice.

Есть лиспособ сделать что-то вроде этого, что работает?

1 Ответ

0 голосов
/ 19 февраля 2019

С вашей типизацией это невозможно, потому что ваш f = fst является полиморфным, и два вызова неявно связаны с другим типом.Если мы сделаем вызовы явными, они станут:

 fst @ (Int,Int) (fst @ ((Int,Int),Int) ((1,2),3))

Можно было бы использовать другой тип для twice, требуя, чтобы аргумент был полиморфной функцией.Для этого требуется Rank2Types:

twice' :: (forall a b . (a, b) -> a) -> ((a,b),c) -> a
twice' f x = f ( f x )

Однако вышеприведенная функция имеет ограниченное использование, поскольку единственным значимым выбором для f является fst - других завершающих функций типа * 1012 нет.*.

Также должна быть возможность использовать классы типов, включая несколько расширений.

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)

Здесь, однако, функция должна быть определена в instance, вместопередачи в качестве параметра.

...