2017-05-12 16 views
6

Aynı kafa yapıcısı kullanılarak iki değerin oluşturulduğunu kontrol eden bir işlev yazabilmek istiyorum. Bu fonksiyon:İki değerde aynı kafa yapıcısına sahip olduğunu kontrol etme

  • veri türü bildiriminin büyüklüğü doğrusal olmamalıdır

  • veri türü

uzatılması halinde çalışmaya devam etmelidir ör Bu (o doğrusal ve ben herhangi bir ekstra yapıcı eklerseniz catchall işlevini geçersiz kılar) tatminkar değildir: OCaml it is possible yılında

data E = A Int | B String | C 

sameCons :: E -> E -> Bool 
sameCons t u = case (t, u) of 
    (A{}, A{}) -> True 
    (B{}, B{}) -> True 
    (C{}, C{}) -> True 
    _   -> False 

tam olarak yapmak için Obj modülünden güvensiz işlevlerini kullanmayı. Haskell'de benzer bir şey yapabilir miyiz (ghc'ye özel bir çözüm de var)?

+0

Türünüzü bir "Veri" örneği yapabilir misiniz? –

+0

Örneğinizin "doğrusal" olduğunu söylediğinizde derleyici uygulamasının işlemsel yönleri hakkında bir varsayım yapıyorsunuz. Örneğin GHC, iç içe geçmiş vakalara tuple'daki durumu genişletir, bu da bir sıçrama tablosuna veya ikili aramaya derlenecektir – jberryman

+1

GHC hakkında herhangi bir varsayım yapmadan, yazılması gereken kod satırlarının sayısı lineerdir. – amalloy

cevap

6

Data türetmek istiyorsanız, gitmekte fayda vardır.

{-# LANGUAGE DeriveDataTypeable #-} 

import Data.Data 

data E = A Int | B String | C deriving (Typeable, Data) 

sameCons :: E -> E -> Bool 
sameCons x y = toConstr x == toConstr y 

ghci> sameCons (A 1) (A 3) 
True 
ghci> sameCons (A 1) (C) 
False 
+6

'sameCons :: Veriler a => a -> a -> Bool; sameCons = (==) \ 'üzerinde \' toConstr' – amalloy

3

Ayrıca GHC.Generics ile yapabilirsiniz, ancak Orgazoid cevabı daha klişe var.

{-# LANGUAGE DeriveGeneriC#-} 
{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE TypeOperators #-} 

import Data.Function (on) 
import GHC.Generics 

class GSameCons f where 
    gSameCons :: f p -> f p -> Bool 

instance GSameCons f => GSameCons (D1 c f) where 
    gSameCons (M1 a) (M1 b) = gSameCons a b 

instance (GSameCons f, GSameCons g) => GSameCons (f :+: g) where 
    gSameCons (L1 a) (L1 b) = gSameCons a b 
    gSameCons (R1 a) (R1 b) = gSameCons a b 
    gSameCons _ _ = False 

instance GSameCons (C1 c f) where 
    gSameCons _ _ = True 

data E = A Int | B String | C deriving Generic 

sameCons :: (GSameCons (Rep a), Generic a) => a -> a -> Bool 
sameCons = gSameCons `on` from 

main = do 
    print (sameCons (A 1) (A 2)) 
    print (sameCons (B "") C)