What is the shortest way to create a list of entries?

Suppose I have a record definition

data Zone = Zone
  { zId      :: Int -- this zone ID
  , zOwnerId :: Int -- the player who owns this zone (-1 otherwise)
  , zPodsP0  :: Int -- player 0 PODs on this zone
  , zPodsP1  :: Int -- player 1 PODs on this zone
  , zPodsP2  :: Int -- player 2 PODs on this zone (always 0 for a two player game)
  , zPodsP3  :: Int -- player 3 PODs on this zone (always 0 for a two or three player game)
  } deriving Show

What are the shortcuts for creating a record from [String]read fromgetLine

zones <- replicateM zoneCount $ fmap (mkZone . words) getLine

This is the best I can do so far.

{-# LANGUAGE NamedFieldPuns #-}

mkZone :: [String] -> Zone
mkZone xs = Zone {zId, zOwnerId, zPodsP0, zPodsP1, zPodsP2, zPodsP3}
  where [zId, zOwnerId, zPodsP0, zPodsP1, zPodsP2, zPodsP3] = map read xs

I often use this template when playing the codingame bot program . It would be nice if there was a better way to do this.

+4
source share
3 answers

RecordWildCards removes half of your template.

{-# LANGUAGE RecordWildCards #-}

mkZone :: [String] -> Zone
mkZone xs = Zone {..}
  where [zId, zOwnerId, zPodsP0, zPodsP1, zPodsP2, zPodsP3] = map read xs
+8
source

You can do this with SYB, for example:

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}

import Data.Data
import Control.Monad.State

data Zone = Zone { zId, zOwnerId, zPodsP0, zPodsP1, zPodsP2, zPodsP3 :: Int }
    deriving (Show, Data)

main = do
    print (mygread ["1", "2", "3", "4", "5", "6"] :: Maybe Zone)
    print (mygread ["a", "2", "3", "4", "5", "6"] :: Maybe Zone)
    print (mygread ["1", "2", "3", "4", "5"] :: Maybe Zone)

mygread :: forall a . Data a => [String] -> Maybe a
mygread = evalStateT (fromConstrM read' constr)
  where
    constr = head . dataTypeConstrs . dataTypeOf $ (undefined :: a)
    read' :: forall a . Data a => StateT [String] Maybe a
    read' = do
        x:xs <- get
        put xs
        lift . fmap fromConstr . readConstr (dataTypeOf (undefined :: a)) $ x

Conclusion:

Just (Zone {zId = 1, zOwnerId = 2, zPodsP0 = 3, zPodsP1 = 4, zPodsP2 = 5, zPodsP3 = 6})
Nothing
Nothing

You only need to make your type an instance of Data ( deriving Data).

+1
source

, Id RecordWildCards . , , : , !

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Dynamic (dynApp, fromDynamic, toDyn)
import Data.List (foldl')
import Data.Typeable (Typeable)

-- Add the 'Typeable' instance to enable runtime type information.
data Zone = Zone
  { zId, zOwnerId, zPodsP0, zPodsP1, zPodsP2, zPodsP3 :: Int
  } deriving (Show, Typeable)

mkZone :: [String] -> Maybe Zone
mkZone = fromDynamic . foldl' dynApp (toDyn Zone) . map (toDyn . readInt)
  where

    -- This type-specialised 'read' avoids an ambiguous type.
    readInt :: String -> Int
    readInt = read

Zone, :

Int -> Int -> Int -> Int -> Int -> Int -> Zone

Int, , :

Int -> Int -> Int -> Int -> Int -> Zone
Int -> Int -> Int -> Int -> Zone
Int -> Int -> Int -> Zone
Int -> Int -> Zone
Int -> Zone
Zone

:

> mkZone ["1", "2", "3", "4", "5", "6"]
Just (Zone {zId = 1, zOwnerId = 2, zPodsP0 = 3, zPodsP1 = 4, zPodsP2 = 5, zPodsP3 = 6})

, Nothing, :

> mkZone ["1", "2", "3", "4", "5"]
Nothing

, , :

> mkZone ["1", "2", "3", "4", "5", "6", "7"]
*** Exception: Type error in dynamic application.
Can't apply function <<Zone>> to argument <<Int>>

dynApply dynApp, Maybe . Maybe, Text.Read.readMaybe :

{-# LANGUAGE DeriveDataTypeable #-}

import Control.Monad ((<=<))
import Data.Dynamic (Dynamic, dynApply, fromDynamic, toDyn)
import Data.List (foldl')
import Data.Typeable (Typeable)
import Text.Read (readMaybe)

data Zone = Zone { … } deriving (Show, Typeable)

mkZone :: [String] -> Maybe Zone
mkZone = fromDynamic <=< foldl' go (Just (toDyn Zone)) . map readInt
  where

    go :: Maybe Dynamic -> Maybe Int -> Maybe Dynamic
    go mAcc mx = do
      acc <- mAcc
      x <- mx
      dynApply acc $ toDyn x

    readInt :: String -> Maybe Int
    readInt = readMaybe

, , .

0

Source: https://habr.com/ru/post/1679634/


All Articles