Универсальный тип трансформеров в Хаскеле
Логически этоМожно определить универсальную функцию преобразования, которая может преобразовывать из любого типа в любой тип.
Возможный путь:
{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE FlexibleInstances #-}
class FromTo a b where
fromTo:: a->b
instance FromTo a a where fromTo = id
instance FromTo Int Double where fromTo = fromIntegral
instance FromTo Int Float where fromTo = fromIntegral
instance FromTo Integer Double where fromTo = fromIntegral
instance FromTo Integer Float where fromTo = fromIntegral
instance FromTo Double Int where fromTo = round
instance FromTo Double Integer where fromTo = round
instance FromTo Float Int where fromTo = round
instance FromTo Float Integer where fromTo = round
-- e.t.c.
Ну, это работаетсидеть'с возможностью расширения. Но это'Это очень громоздко, потому что я должен перечислить любой случай, который я хочу использовать.
Есть ли хорошие решения для этого?
Одно правильное решение можно было бы сделать так, если бы оно было правильным(но это'не)
{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE FlexibleInstances #-}
{-#LANGUAGE InstanceSigs #-}
class FromTo a b where
fromTo:: a->b
instance (Integral a, Num b) => FromTo a b where
fromTo::a->b
fromTo x = (fromIntegral x)
{---Commented, because addition breaks program.-------------------------------
instance (RealFrac a, Integral b) => FromTo a b where
fromTo::a->b
fromTo x = (round x)
-}
Возможно, это было бы возможно, если бы существовало расширение некоторых наборов типов (псевдокод, подобный Haskell):
{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE FlexibleInstances #-}
{-#LANGUAGE InstanceSigs #-}
{-#LANGUAGE TypeSets #-}
class FromTo a b where
fromTo:: a->b
instance setfrom (Integral a, Num b). (Integral a, Num b) => FromTo a b where
fromTo::a->b
fromTo x = (fromIntegral x)
instance setfrom (RealFrac a, Integral b). (RealFrac a, Integral b) => FromTo a b where
fromTo::a->b
fromTo x = (round x)
setfrom C1 a.
здесь следует определить множество типов, используя информацию об экземплярах изC1
учебный класс. Компилятор должен проверить, пересекаются ли экземпляры. Другая возможная конструкция этого расширенияset (T1,T2,...,TN) a.
, что позволяет просто определить набор типов.
UPD 1
1-е решение может быть улучшено таким образом (но этонекорректный путь):
{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE FlexibleInstances #-}
class FromTo a b where
fromTo:: a->b
instance FromTo a a where fromTo = id
instance Num b => FromTo Int b where
fromTo x = fromIntegral x
instance Num b => FromTo Integer b where
fromTo x = fromIntegral x
instance Integral b => FromTo Float b where
fromTo x = round x
instance Integral b => FromTo Double b where
fromTo x = round x
Но это'все еще не хорошо и, кроме того,дает совпадения при звонке в интерактивном режиме:
*Main> fromTo (10::Double) ::Double
:108:1:
Overlapping instances for FromTo Double Double
arising from a use of `fromTo'
Matching instances:
instance FromTo a a -- Defined at 4.hs:8:10
instance Integral b => FromTo Double b -- Defined at 4.hs:19:10
In the expression: fromTo (10 :: Double) :: Double
In an equation for `it': it = fromTo (10 :: Double) :: Double