Why is `cost` a `RobotPart -> Double` and not just `Double`

I’m sure there are lots of problems/sub-optimal things in this code (like that funny destructureIt that needs to go) and all comments are welcome, but I’m currently stuck on why in partToText, partId is an Int as expected but cost is a RobotPart -> Double instead of just a Double?

data RobotPart = RobotPart
  { 
    partId :: Int
  , name :: T.Text
  , description :: T.Text
  , cost :: Double
  } deriving Show


destructureIt :: Either a1 (a2, b) -> a2
destructureIt (Right (a,b)) = a

toRobotPart :: [T.Text] -> RobotPart
toRobotPart part = RobotPart {
      partId = a0
    , name = a1
    , description = a2
    , cost = a3
  }
  where a0 = destructureIt (TR.decimal (head part))
        a1 = part !! 1
        a2 = part !! 2
        a3 = destructureIt (TR.double (part !! 3))

numToText :: (Num a, Show a) => a -> T.Text
numToText num = T.pack (show num)

partToText :: RobotPart -> T.Text
partToText RobotPart{partId=partId, name=name, description=description, cost=const} = T.concat [numToText partId, name, description, cost]

printParts :: [RobotPart] -> String
printParts parts = "x"

main :: IO ()
main = do
  let file = "/.../parts.csv"
  contents <- TIO.readFile file
  let p1 = T.lines contents
  let p2 = tail p1
  let p3 = map (T.splitOn ",") p2
  let p4 = map toRobotPart p3
  print p4

cost is a field label.

data Foo = Foo { myX :: Int,
                 myY :: Int}

Means you have two selectors (myX :: Foo -> Int and myY :: Foo -> Int) for free, without having to write them yourself.

Field labels can also be used to construct new values.

newFoo :: Foo
newFoo = let a = Foo 10 12
         in a { myX = 7 }              -- Foo 7 12

To add to what @f-a said, when you destructured your RobotPart in your partToText function, you made a variable partId to hold the value of the partId of your RobotPart input. This shadowed the field label, so inside that function if you said partId, you’d get the destructured value instead. But your cost field got destructured into a variable named const (presumably a typo), and no shadowing is happening. So inside that function cost still refers to the field label that will extract a cost from a RobotPart, while there’s also a variable named const that holds the Double value you’re looking for.

5 Likes

Thank you!. I was about to make a longish post of my observations but you saved me. Problem is just a typo.

1 Like

Here is what I think is the answer to the original question: “Why is cost a RobotPart -> Double and not just Double?”

As in the screenshot above, partId is Int. Similary name & description are Text but oddly cost is RobotPart -> Double. That is due to the typo (cost=const should be cost=cost). Since cost was not defined within the function the data constructor cost was being shown instead.

(Likely obvious to many but wasn’t to me)