 # 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"
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)