2016-07-08 8 views
3

Ich habe DatentypConstructing Haskell-Datentypen mit vielen Feldern

data Constants = Constants { x1 :: Int, x2 :: Int, ... , x100 :: Int } 

Namen x1, x2, ..., x100 unregelmäßige Namensgebung haben.

Gibt es eine elegante Möglichkeit, Konstanten Objekt aus der Liste der 100 Int-Werte zu erstellen?

mkConstants :: [Int] -> Constants 
mkConstants [x1, x2, ..., x100] = Constants x1 x2 ... x100 -- The bad way 

Was ist mit umgekehrter Aufgabe?

extractInts :: Constants -> [Int] 
extractInts (Constants x1 x2 ... x100) = [x1, x2, ..., x100] -- The bad way 
+2

Kurze Antwort: nein. Woher kommt die Liste? Im Allgemeinen, wenn ich Listen sehe, die eine bestimmte Größe haben müssen (100 Elemente in diesem Fall), werde ich etwas verdächtig über die Verwendung einer Liste. Vielleicht baue ich einfach 'Konstanten' auf, wo du gerade die Liste machst? – Alec

+1

Konstanten ist ein Beispiel für einen Typ mit einer großen Anzahl von Feldern. Wirklich Beispiel: https://www.stackage.org/haddock/lts-6.6/ghc-7.10.3/DynFlags.html#t:PlatformConstants – Bet

+0

Liste kommt von IO-Aktion – Bet

Antwort

8

Bearbeiten: siehe Reading long data structure in Haskell für eine modifizierte Version, wenn die Datensatzfelder von unterschiedlicher Art sind (d. H. nicht alle Ints).


Eine Möglichkeit wäre, Typklassen zu verwenden:

{-# LANGUAGE FlexibleInstances #-} 

data Constants = Constants { a :: Int, b :: Int, c :: Int, d :: Int, e :: Int } 
    deriving Show 

class Cons a where 
    cons :: a -> [Int] -> Maybe Constants 

instance Cons Constants where 
    cons c [] = Just c 
    cons _ _ = Nothing 

instance (Cons a) => Cons (Int -> a) where 
    cons f (x:xs) = cons (f x) xs 
    cons _ _  = Nothing 

dann, wenn die Liste der richtigen Größe:

\> cons Constants [1..5] 
Just (Constants {a = 1, b = 2, c = 3, d = 4, e = 5}) 

und man sonst nichts bekommen:

\> cons Constants [1..4] 
Nothing 
\> cons Constants [1..6] 
Nothing 
+0

Es ist wirklich sehr einfache Lösung.Können Sie eine Lösung für die umgekehrte Aufgabe veröffentlichen - von Konstanten zu [Int]? – Bet

+0

@Bet das Gegenteil wäre eine ganz andere Sache, und würde voraussichtlich Vorlage Haskell (die ich nicht weiß) erfordern. Ich würde vorschlagen, die hinzugefügte Bearbeitung rückgängig zu machen und den umgekehrten Fall in einer neuen Frage zu stellen. –

3

Hier ist eine Proof-of-Concept-Art und Weise dies über generische Programmierung zu tun (in diesem Fall über generics-sop). Ob dies ein geeigneter Ansatz ist Ihr eigentliches Problem hängt von einer Vielzahl von Faktoren, die zu lösen, die ich zur Zeit nicht beurteilen:

{-# LANGUAGE DeriveGeneric, ScopedTypeVariables, DataKinds, TypeFamilies, FlexibleContexts, TypeOperators, PolyKinds #-} 
{-# OPTIONS_GHC -fcontext-stack=200 #-} 

module Constants where 

import Data.Maybe 
import Generics.SOP 
import qualified GHC.Generics as G 

data Constants = 
    Constants 
    { x00 :: Int, x01 :: Int, x02 :: Int, x03 :: Int, x04 :: Int, x05 :: Int, x06 :: Int, x07 :: Int, x08 :: Int, x09 :: Int 
    , x10 :: Int, x11 :: Int, x12 :: Int, x13 :: Int, x14 :: Int, x15 :: Int, x16 :: Int, x17 :: Int, x18 :: Int, x19 :: Int 
    , x20 :: Int, x21 :: Int, x22 :: Int, x23 :: Int, x24 :: Int, x25 :: Int, x26 :: Int, x27 :: Int, x28 :: Int, x29 :: Int 
    , x30 :: Int, x31 :: Int, x32 :: Int, x33 :: Int, x34 :: Int, x35 :: Int, x36 :: Int, x37 :: Int, x38 :: Int, x39 :: Int 
    , x40 :: Int, x41 :: Int, x42 :: Int, x43 :: Int, x44 :: Int, x45 :: Int, x46 :: Int, x47 :: Int, x48 :: Int, x49 :: Int 
    , x50 :: Int, x51 :: Int, x52 :: Int, x53 :: Int, x54 :: Int, x55 :: Int, x56 :: Int, x57 :: Int, x58 :: Int, x59 :: Int 
    , x60 :: Int, x61 :: Int, x62 :: Int, x63 :: Int, x64 :: Int, x65 :: Int, x66 :: Int, x67 :: Int, x68 :: Int, x69 :: Int 
    , x70 :: Int, x71 :: Int, x72 :: Int, x73 :: Int, x74 :: Int, x75 :: Int, x76 :: Int, x77 :: Int, x78 :: Int, x79 :: Int 
    , x80 :: Int, x81 :: Int, x82 :: Int, x83 :: Int, x84 :: Int, x85 :: Int, x86 :: Int, x87 :: Int, x88 :: Int, x89 :: Int 
    , x90 :: Int, x91 :: Int, x92 :: Int, x93 :: Int, x94 :: Int, x95 :: Int, x96 :: Int, x97 :: Int, x98 :: Int, x99 :: Int 
    } 
    deriving (Show, G.Generic) 

instance Generic Constants 

fromConstantList :: 
    forall a c xs . (Generic a, Code a ~ '[ xs ], All ((~) c) xs) => 
    [c] -> a 
fromConstantList = 
    to . SOP . Z . hcmap (Proxy :: Proxy ((~) c)) (I . unK) . fromJust . fromList 

toConstantList :: 
    forall a c xs . (Generic a, Code a ~ '[ xs ], All ((~) c) xs) => 
    a -> [c] 
toConstantList = 
    hcollapse . hcmap (Proxy :: Proxy ((~) c)) (K . unI) . unZ . unSOP . from 

unZ :: NS f (x ': xs) -> f x 
unZ (Z x) = x 

test1 :: Constants 
test1 = fromConstantList [1..100] 

test2 :: [Int] 
test2 = toConstantList test1 

In GHCi (dies ist mit der Version 7.10.3, siehe unten):

*Constants> test1 
Constants {x00 = 1, x01 = 2, x02 = 3, x03 = 4, x04 = 5, x05 = 6, x06 = 7, x07 = 8, x08 = 9, x09 = 10, x10 = 11, x11 = 12, x12 = 13, x13 = 14, x14 = 15, x15 = 16, x16 = 17, x17 = 18, x18 = 19, x19 = 20, x20 = 21, x21 = 22, x22 = 23, x23 = 24, x24 = 25, x25 = 26, x26 = 27, x27 = 28, x28 = 29, x29 = 30, x30 = 31, x31 = 32, x32 = 33, x33 = 34, x34 = 35, x35 = 36, x36 = 37, x37 = 38, x38 = 39, x39 = 40, x40 = 41, x41 = 42, x42 = 43, x43 = 44, x44 = 45, x45 = 46, x46 = 47, x47 = 48, x48 = 49, x49 = 50, x50 = 51, x51 = 52, x52 = 53, x53 = 54, x54 = 55, x55 = 56, x56 = 57, x57 = 58, x58 = 59, x59 = 60, x60 = 61, x61 = 62, x62 = 63, x63 = 64, x64 = 65, x65 = 66, x66 = 67, x67 = 68, x68 = 69, x69 = 70, x70 = 71, x71 = 72, x72 = 73, x73 = 74, x74 = 75, x75 = 76, x76 = 77, x77 = 78, x78 = 79, x79 = 80, x80 = 81, x81 = 82, x82 = 83, x83 = 84, x84 = 85, x85 = 86, x86 = 87, x87 = 88, x88 = 89, x89 = 90, x90 = 91, x91 = 92, x92 = 93, x93 = 94, x94 = 95, x95 = 96, x96 = 97, x97 = 98, x98 = 99, x99 = 100} 
*Constants> test2 
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100] 

Interessanterweise als ich versuchte, diese mit ghc-8.0.1 zu kompilieren (dann müssen Sie die Option -fcontext-stack mit -freduction-depth ersetzen, auch), bekam ich einen unerwarteten internen GHC Fehler, die ich weiter zu untersuchen, haben ...

+0

Der Fehler, den ich bekommen habe, könnte mit https://ghc.haskell.org/trac/ghc/ticket/12041 identisch sein, was behoben zu sein scheint. – kosmikus

+0

Ich habe die entgegengesetzte Richtung hinzugefügt. (Aber die andere Lösung ist sicherlich einfacher.) – kosmikus

+0

Ich kann Ihren Code nicht kompilieren. ghc-7.10.3 versuchen, es bereits 10 Minuten und Speicherverbrauch 3 GB zu kompilieren! – Bet

Verwandte Themen