2015-09-14 15 views
6

Supponiamo che io sonoÈ possibile che due diversi typeclass abbiano gli stessi nomi di metodo?

class Foo a where 
    (++=) :: a -> a -> a 
    cool :: (a -> b -> b) -> a -> b 

e vuole fare

class Bar a where 
    (++=) :: (a -> b) -> a -> b 
    magic :: a -> b 

che ha un nome di un metodo di sovrapposizione, (++=). C'è un modo per farlo?

+0

In OOP, i metodi con lo stesso nome sono consentiti perché il tipo dell'oggetto 'this' può essere disambiguo tra loro. In Haskell, non c'è 'this' around: metodi per' Foo a' non implicitamente accettano un argomento 'a'. Anche se lo facessero, digitare l'inferenza diventerebbe piuttosto complicato, dal momento che è necessario calcolare il tipo di "questo" _prima_ si può conoscere il tipo del metodo. Nella maggior parte dei linguaggi OOP, non c'è o nessuna inferenza di tipo w.r.t. lingue funzionali, quindi questo non è un problema lì. – chi

+2

Inoltre, queste sono funzioni non metodi, per la precisione. –

+4

@Erik Alik: In realtà, anche se è molto diverso dal concetto OO, [la parola 'metodo' è tecnicamente corretta] (https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3) . –

risposta

2

Questa domanda ha una sottile "no ma sì" tipo di risposta, che richiede di andare in tre concetti:

  1. nomi qualificati vs. nomi non qualificati
  2. moduli e le importazioni
  3. Aliasing

Punto 1: ogni definizione in Haskell ha un nome breve e non qualificato come map e un nome lungo e qualificato come Data.List.map.

Punto 2: quando si importa un modulo in un altro, è possibile eseguire un'importazione qualificata o non qualificata. Quando si utilizza un'importazione non qualificata, i nomi dei moduli esterni che si inseriscono verranno sottoposti a alias sotto i loro nomi brevi. Quando si esegue un'importazione qualificato, saranno disponibili solo con un nome modificato:

import qualified Data.Map as Map 

Ora, nel modulo in cui questo è apparso, la funzione Data.Map.map è visibile sotto lo pseudonimo Data.map.

Terzo punto: ciò significa che ogni definizione Haskell ha un nome completo determinato dal suo nome breve e dal modulo in cui è definito, ma anche da alias non qualificato o parzialmente qualificato in ogni modulo in cui viene importato.

Ora, la tua domanda ha due risposte:

  1. due classi diverse non possono avere metodi che condividono lo stesso completo nome. Pertanto, se si definiscono le classi Foo e Bar nello stesso modulo, ciò non riuscirà.
  2. due classi diverse possono avere metodi che condividono lo stesso nome non qualificato , finché i loro nomi completi sono diversi-cioè., Sono definite in diversi moduli. Per utilizzare entrambi all'interno di un modulo client, tuttavia, sarà necessario almeno un'importazione qualificata in modo che gli alias dall'importazione non entrino in conflitto.
+1

Nel tuo esempio intendi' Mappa .map', o 'importa Data.Map qualificati come dati', giusto? – suffi

4

No, non è possibile, almeno all'interno dello stesso modulo. È possibile possibile dichiarare class Foo e class Bar in due moduli diversi e importarli ciascuno nello stesso file, ma sarà comunque necessario immettere qualify almeno una di quelle importazioni per evitare conflitti.

+8

Quindi è "sì, puoi, se ..." non "no tu non riesci :) –

+2

@ErikAllik Essi letteralmente non possono avere gli stessi nomi, la qualificazione li fa avere nomi diversi –

0

Di seguito compila senza errori:

principale.HS:

module Main where 

import qualified Foo 
import Bar 

instance Foo.Foo Char where 
    c1 ++= c2 = c1 

instance Bar Char where 
    f ++= c = f c 

main = do 
    putStrLn $ [ 'a' Foo.++= 'b' ] 

Foo.hs:

module Foo where 

class Foo a where 
    (++=) :: a -> a -> a 

Bar.hs:

module Bar where 

class Bar a where 
    (++=) :: (a -> b) -> a -> b 

Quindi, in altre parole, non abbiamo bisogno di fare riferimento a ++= utilizzando il suo nome completo all'interno della dichiarazione di istanza, ma quando viene utilizzato all'interno di main, dobbiamo specificare quale ++= stiamo parlando. Nella dichiarazione di istanza, abbiamo già definito l'ambito per ++=, mentre main non sapremmo a quale di questi si stava facendo riferimento, se avessimo usato importazioni non qualificate. Pertanto, se tutto ciò che volevamo fare era definire istanze di classe, non avremmo bisogno dell'importazione qualificata.

Problemi correlati