Choć jest możliwe do zrobienia takiego przeciążenia w Haskell, nie jest uważane za idiomatyczne, i prawdopodobnie będzie prowadzić do błędów mylące później. Zamiast tego, należy po prostu określić funkcje, które konstruują dane:
point :: Rectangle
point = Rectangle 0 0
line :: Length -> Rectangle
line l = Rectangle l 0
square :: Int -> Rectangle
square a = Rectangle a a
To pozwala dać jasne nazwy, które opisują semantykę każdego przeciążeniem, zamiast polegania na liczbę i rodzaj argumentów danego disambiguate którego oznaczać.
Jednakże, jeśli chcesz napisać wersję przeciążony, można to zrobić z łatwością typeclasses:
class MakeRectangle a where
rectangle :: a
instance MakeRectangle Rectangle where
rectangle = Rectangle 0 0
instance MakeRectangle (Length -> Rectangle) where
rectangle l = Rectangle l 0
instance MakeRectangle (Length -> Width -> Rectangle) where
rectangle = Rectangle
Musisz {-# LANGUAGE FlexibleInstances #-}
w górnej części pliku do kompilowania to. Taka sztuczka jest używana przez standardową bibliotekę Text.Printf
, ale nie uważam jej za szczególnie dobry przykład przeciążania w Haskell; prawie zawsze istnieje pewna struktura dla typu przeciążonej wartości, podczas gdy tutaj cała jego struktura jest dyktowana przez instancję, która może stać na drodze do wnioskowania o typie; nie tylko to, ale nie ma żadnych rozsądnych praw, które rządzą instancjami (w rzeczywistości typ jest zbyt ogólny, aby można było na to zezwolić).
Ale jeśli naprawdę chcesz to zrobić, możesz i choć zwykle jest to zły pomysł, czasami (jak w przypadku printf
) jest to jedyny sposób na osiągnięcie pożądanego interfejsu.
Aby to wypróbować w GHCi, musisz określić typy których używasz jednoznacznie, czy to nie będzie w stanie rozwiązać instancje:
GHCi> rectangle :: Rectangle
Rectangle 0 0
GHCi> rectangle (1 :: Length) :: Rectangle
Rectangle 1 0
GHCi> rectangle (1 :: Length) (2 :: Width) :: Rectangle
Rectangle 1 2
Nie zawracałbym sobie głowy modelowaniem haskell po C++; to po prostu doprowadzi do dużego bólu. Dlaczego drugi konstruktor prostokąta jest linią? Myślę, że bardziej sensowną implementacją byłoby domyślne (1, 1), a jeśli otrzymasz jedną int, podaj (x, x), aby utworzyć kwadrat. – alternative
Słyszałeś o liście inicjalizacyjnej konstruktora? –
@ VladLazarenko: Czy słyszałeś o ludziach, którzy wciąż się uczą? (Podpowiedź: jesteś wśród nich, wszyscy są) –