Различное поведение между числовыми литералами и параметрами функции с ограничениями в Haskell

Я пытался выяснить более тонкие части системы типов Haskell, написав библиотеку Vector. В идеале мне бы хотелось иметь перегруженную операцию умножения векторов, которая работает немного как C++, т. е. вы можете умножать вектор любого размера на скаляр в любом порядке. Я попытался объединить несколько классов типов параметров и расширение семейств типов, чтобы сделать это:

{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}

data Vec2 a = Vec2 (a,a) deriving (Show, Eq, Read)

class Vector a where
    (<+>) :: a -> a -> a

class VectorMul a b where
    type Result a b
    (<*>) :: a -> b -> Result a b

instance (Num a) => Vector (Vec2 a) where
    Vec2 (x1,y1) <+> Vec2 (x2,y2) = Vec2 (x1+x2, y1+y2)

instance (Num a) => VectorMul (Vec2 a) a where
    type Result (Vec2 a) a = (Vec2 a)
    Vec2 (x,y) <*> a = Vec2 (x*a, y*a)

works :: (Num a) => Vec2 a -> a -> Vec2 a
works a b = a <*> b

Этот код работает, по крайней мере, при использовании функции works. Но когда я пытаюсь ввести простое выражение, такое как Vec2 (3,4) <*> 5, в GHCi, он сообщает, что переменные типа (Num xx) неоднозначны. Это странно для меня... что я упускаю в этом случае? Haskell должен иметь возможность выбирать один и тот же произвольный тип для литералов, чтобы выражение типа работало (как это происходит в функции works).


person mysterymath    schedule 18.08.2013    source источник
comment
В works вы явно говорите a в Vec2 a, а второй аргумент a имеет тот же тип.   -  person Satvik    schedule 18.08.2013
comment
Этот вопрос действительно касается типа по умолчанию и почему он не удар здесь, как вы, кажется, ожидаете.   -  person leftaroundabout    schedule 19.08.2013


Ответы (1)


Попробуйте написать

Vec2 (3,4 :: Int) <*> (5 :: Int)

В Vec2 (3,4) <*> 5 не гарантируется, что 3,4 ::Num a и 5 :: Num b имеют одинаковые a и b

person wit    schedule 18.08.2013