8
votes

In Elm what is the correct way to take my Model and implement a toString function?

The type I am looking for would be toString : Model -> String, I am able to make a similar function with the type of toStr : Model -> String but I would think I would want the function to be called toString.

Example program (the Coin Changer kata):

module CoinChanger where

import Html exposing (..)
import StartApp.Simple as StartApp
import Signal exposing (Address)
import Html.Attributes exposing (..)
import Html.Events exposing (on, targetValue)
import String


---- MAIN ----


main =
  StartApp.start 
  {
       model = emptyModel
      ,update = update
      ,view = view
  }


---- Model ----


type alias Model =
    {
        change : List Int
    }


emptyModel : Model
emptyModel =
    {
        change = []
    }


---- VIEW ----


toStr : Model -> String
toStr model =
  model.change
  |> List.map (\coin -> (toString coin) ++ "¢")
  |> String.join ", " 


view : Address String -> Model -> Html
view address model =
  div []
  [
      input
      [
          placeholder "amount to make change for"
      ,   on "input" targetValue (Signal.message address)
      ,   autofocus True
      -- style  
      ]
      []
  ,   div []
      [
          text (toStr model)
      ]
  ]


---- UPDATE ----


changeFor : Int -> List Int
changeFor amount =
  [ 25, 10, 5, 1 ]
  |> List.foldl
    (\coin (change, amount)
      -> ( change ++ List.repeat (amount // coin) coin
         , amount % coin)
    )
    ([], amount)
  |> fst



update : String -> Model -> Model
update change model =
  { model | change =
      case String.toInt change of
        Ok amount 
            -> changeFor amount

        Err msg
            -> []
  }

I would think the correct way to do this would be to call the function toString, but that gives me the following error from the compiler:

Detected errors in 1 module. -- TYPE MISMATCH ----------------------------------------------- CoinChanger.elm

The type annotation for toString does not match its definition.

42│ toString : Model -> String ^^^^^^^^^^^^^^^ The type annotation is saying:

{ change : List Int } -> String

But I am inferring that the definition has this type:

{ change : List { change : List Int } } -> String

Renaming the function to toStr (or something not called toString) fixes the issue but seems wrong. What is the correct way to do this?

2

2 Answers

5
votes

The problem is that, calling your function toString, you are overriding the toString function of the Basics module, which you are using at line 45.

To avoid this, you'll need to import the Basics module and use Basics.toString instead of simply toString to eliminare the ambiguity

3
votes

The accepted answer is well out of date for anyone writing Elm 0.19+. The current solution is to write your own toString function for the type you want converted. There is a Debug.toString for use during development but its use in your code will prevent building for production.