data Rank = Ten | Jack | Knight | Queen | King deriving(Show)
data Value = I | II | III | IV | V | VI | VII | VIII | IX | X |
XI | XII | XIII | XIV | XV | XVI | XVII | XVIII | XIX | XX | XXI | Skeench deriving(Show)
data Card = Clubs Rank
| Diamonds Rank
| Spades Rank
| Hearts Rank
| Tarock Value deriving (Show)
cards= foldr (++) [] (map (\x -> map ($ x) [Diamonds, Clubs, Hearts, Spades]) [Ten, Jack, Knight, Queen, King]) ++
(map Tarock [I, II,III,IV,V,VI,VII,VIII,IX,X,XI,XII,XIII,XIV,XV,XVI,XVII,XVIII,XIX,XX,XXI,Skeench])
Második megközelítésben:
data Rank = Ten | Jack | Knight | Queen | King deriving(Show,Enum)
data Value = I | II | III | IV | V | VI | VII | VIII | IX | X
| XI | XII | XIII | XIV | XV | XVI | XVII | XVIII | XIX | XX
| XXI | Skeench deriving(Show,Enum)
data Card = Clubs Rank
| Diamonds Rank
| Spades Rank
| Hearts Rank
| Tarock Value deriving (Show)
cards= concatMap (\x -> map ($ x) [Clubs, Hearts, Diamonds, Spades]) [Ten .. King] ++ map Tarock [I .. Skeench]
Alakul ez.
- wachag blogja
- A hozzászóláshoz be kell jelentkezni
Hozzászólások
foldr (++) az rovidebben concat
concat . map az rovidebben concatMap.
hlint sokat segit ezeknek a megtalalasaban..
- A hozzászóláshoz be kell jelentkezni
Kószönöm! Látható, hogy még hiányos a szókincsem.
- A hozzászóláshoz be kell jelentkezni
np. A masik ami utana jutott eszembe: deriving (Show, Enum, Bounded) es akkor a hosszu felsorolas lecserelheto [minBound .. maxBound] ahelyett hogy [I, II .. ]
mivel a minBound :: (Bounded a) => a barmilyen a -ra igy szukseg lehet egy explicit tipus kiirasra - ha a contextbol nem kovetkezik. vagyis igy [I, II, III ...] -t lecsereled ([minBound .. maxBound] :: [Value])
szerk:
a Bounded -et elhagyva (nem folhasznalva) csak Enum kent:
[I .. Skeench] es akkor nem kell explicit tipus sem - hiszen egyertelmu.
- A hozzászóláshoz be kell jelentkezni
No, pontosan ezt kerestem.
- A hozzászóláshoz be kell jelentkezni
Esetleg igy olvashatobb: [f r | f <- [Clubs, Hearts, Diamonds, Spades], r <- [Ten .. King]] ++ [Tarrock v | v <- [I .. Skeench]]
- A hozzászóláshoz be kell jelentkezni
Van még mit tanulnom. Jogos :-)
- A hozzászóláshoz be kell jelentkezni
Ez miért működik?
Úgy értem, hogyan képez listát, ha az f és r közt nincs művelet?
Ez miért nem működik: [a b | a <- [1..10], b <- [11..20]]
?
Szerk. Azt hiszem leesett.
A Cards kapcsolja őket össze?
- A hozzászóláshoz be kell jelentkezni
A Card tipus adat konstruktorai egyvaltozos fuggvenyek:
Clubs :: Rank -> Card
Diamonds :: Rank -> Card
Spades :: Rank -> Card
Hearts :: Rank -> Card
Tarock :: Value -> Card
igy f :: Rank -> Card fv. (a Tarrock kimarad mert annak mas a tipusa). f r :: Card ahol r :: Rank. Egyebkent olyan listat nem is lehet csinalni hogy [ Clubs, Tarrock ] a tipusok miatt. Viszont [Clubs, Diamonds ] :: [ Rank -> Card ] fuggvenyek listaja.
- A hozzászóláshoz be kell jelentkezni
Elméleti kérdés:
Mivel a függvény elvben ugyanolyan, mint bármi más érték, el lehet-e érni ezt:
[Clubs..Spades] ? Tehát a konstruktor lehet-e felsorolható? (Gyanúm szerint sajnos nem, pedig ez volna az igazán szép imho)
- A hozzászóláshoz be kell jelentkezni
Maga a konstruktor nem lesz folsorolhato mert http://hackage.haskell.org/package/base-4.7.0.2/docs/Prelude.html#t:Enum
class Enum a where
fromEnum :: a -> Int -- fuggveny a problemas. (a toEnum az definialhato lenne).
Megpedig azert mert ha a :: Rank -> Card akkor a fromEnum :: (Rank -> Card) -> Int viszont fv-re nem lehet pattern matchelni. (ill fv-eken nincs Eq sem). Tehat nem tudsz olyat irni, hogy
fromEnum Clubs = ...
fromEnum Hearts = ...
Viszont a Card az lehet enum
cards = [f r | f <- [Clubs, Hearts, Diamonds, Spades], r <- [Ten .. King]] ++ [Tarrock v | v <- [I .. Skeench]]
instance Enum Card where
toEnum n = cards !! n
fromEnum c = fromJust $ elemIndex c cards
es akkor [Clubs Ten .. Tarrock Skeench]. (az elemIndex miatt kell szarmaztatni egy Eq instance-t is mindenhol vagy pattern match-el imlementalni a fromEnum-ot.)
viszont igy az enum osszes trukkje is mukodik: [ Clubs Ten .. Clubs King ], es most csak a Ten-ek: [Clubs Ten, Hearts Ten .. Spades Ten] vagy akar visszafele.
- A hozzászóláshoz be kell jelentkezni
Es megis lehet! A trukk, implementalni fromEnum x -et ha x nem osszehasonlithato, v pattern matchelheto.. (x Ten) viszont igen.
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
data Rank = Ten | Jack | Knight | Queen | King deriving(Show,Enum)
data Value = I | II | III | IV | V | VI | VII | VIII | IX | X
| XI | XII | XIII | XIV | XV | XVI | XVII | XVIII | XIX | XX
| XXI | Skeench deriving(Show,Enum)
data Card = Clubs Rank
| Diamonds Rank
| Spades Rank
| Hearts Rank
| Tarock Value deriving (Show)
type CardConstr = Rank -> Card
instance Enum CardConstr where
fromEnum x = case x Ten of
Clubs Ten -> 0
Diamonds Ten -> 1
Spades Ten -> 2
Hearts Ten -> 3
toEnum n = [ Clubs, Diamonds, Spades, Hearts ] !! n
cards = [f r | f <- [Clubs .. Spades], r <- [Ten .. King]] ++ [Tarock v | v <- [I .. Skeench]]
Hozzateszem, ez elege torott kod, mert az Enum instance-unk azt allitja hogy, fol tudja sorolni a Rank -> Card tipust. De a kododtol fuggetlenul barki egy masik modulban (a Card es a Rank lathatosagat folteve), irhat egy Rank -> Card fv.-t ami a felsorolasbol kimarad.
szerk : meg egy utolso simitas... Mivel az Enumunk eltori a szemantikat - valojaban nem a Rank -> Card tipus elemeit soroljuk fel - igy ez futasi ideju exception:
f Ten = Hearts Queen
fromEnum f
mert a fonti kodban (x Ten) Hearts Queen-t ad. Ha nem matchelunk a Ten -re akor a case mar teljes:
fromEnum x = case x Ten of
Clubs _ -> 0
Diamonds _ -> 1
Spades _ -> 2
Hearts _ -> 3
es fromEnum f igy Hearts-ot ad.
szerk2:
A helyes implementacio ez alapjan szinten lehetseges: kepezzuk a Rank -> Card osszes lehetseges lekepezesek listajat valamilyen sorrendben, a toEnum egyszeruen ezt indexeli, a fromEnum meg megnezi hogy a bejovo fuggveny melyik indexuvel adja minden inputra ugyanazt az eredmenyt. Gyors nem lesz, de elmeletileg helyes :)
- A hozzászóláshoz be kell jelentkezni