static-fp icon indicating copy to clipboard operation
static-fp copied to clipboard

Whole Story Recursion Does Not Work in Elm 0.19

Open rue opened this issue 7 years ago • 5 comments

module SumTypes.WholeStorySolution exposing (..)

type Silly a b
  = AsA a
  | AsB b
  | AlsoAsA a

  | AsInt Int

  | AsFloatString Float String
  | AsBoth a b
  | AsIntB Int b

  | AsMaybe (Maybe b)
  | AsMaybeInt (Maybe Int)
  | DeeplySilly (Silly a a) (Silly Int b)
  | NoArg

bVals : Silly a b -> Maybe b
bVals silly =
  case silly of 
    AsB b -> Just b
    AsBoth _ b -> Just b
    AsIntB _ b -> Just b
    AsMaybe (Just b) -> Just b  -- could just be AsMaybe maybe -> maybe
    DeeplySilly _ nested -> bVals nested           -- <--- Problem here
_ -> Nothing

Produces an error on 0.19:

Detected errors in 1 module.                                         
-- TYPE MISMATCH --------------------------------------------- src/SumTypes/WholeStorySolution.elm

The 1st argument to `bVals` is not what I expect:

171|             bVals nested
                       ^^^^^^^^^^
This `nested` value is a:

    Silly Int b

But `bVals` needs the 1st argument to be:

    Silly a b

Hint: Your type annotation uses type variable `a` which means ANY type of value
can flow through, but your code is saying it specifically wants a `Int` value.
Maybe change your type annotation to be more specific? Maybe change the code to
be more general?


rue avatar Nov 19 '18 21:11 rue

Hmm. I'm confused by why it's wrong. Probably missing something obvious. I'll have to try it on PureScript and see if it's also an error there.

I expect there are a lot of 0.19 problems, but I'm going to be slow to fix them. (First I'm looking into just having people install 0.18 instead if I can figure out how.)

marick avatar Nov 19 '18 22:11 marick

It feels like a corner case or possibly even a bug (the function name being bound to the type it was applied to within the function?), but being this new to the language I’m assuming I’m just missing something about the way type variables work. I have seen the "too general" type error before, after all.

This is additionally interesting:

> bVals
<function> : Silly Int a -> Maybe a      -- The inferred type

> AsStringFloat "hi" 4.5 |> bVals
Nothing : Maybe b                                -- …Why is this not an error, it doesn’t conform to the type?

I posted on the Elm slack, too, see if anybody chimes in with an explanation :)

rue avatar Nov 19 '18 23:11 rue

Did you get anything from the Elm slack? I didn't see anything.

I ported the code to PureScript, and it compiles fine:

module Main where

import Prelude
import Data.Maybe (Maybe(..), isNothing)

data Silly a b
  = AsA a
  | AsB b
  | AlsoAsA a

  | AsInt Int

  | AsFloatString Number String
  | AsBoth a b
  | AsIntB Int b

  | AsMaybe (Maybe b)
  | AsMaybeInt (Maybe Int)
  | DeeplySilly (Silly a a) (Silly Int b)
  | NoArg
    
simplify :: forall a b . Silly a b -> Silly a b
simplify silly =
  case silly of
    AsA _ -> silly
    AsB _ -> silly
    _ -> NoArg

bVals1 :: forall a b. Silly a b -> Maybe b
bVals1 silly =
  case silly of 
    AsB b -> Just b
    _ -> Nothing

bVals :: forall a b. Silly a b -> Maybe b
bVals silly =
  case silly of 
    AsB b -> Just b
    AsBoth _ b -> Just b
    AsIntB _ b -> Just b
    AsMaybe (Just b) -> Just b  -- could just be AsMaybe maybe -> maybe
    DeeplySilly _ nested -> bVals nested
    _ -> Nothing

So I'm inclined to call this a bug in Elm. Will file it unless you want to.

marick avatar Nov 21 '18 16:11 marick

No answer as yet—I’ll give it another day and file if nobody has an answer :)

rue avatar Nov 21 '18 22:11 rue

Send me a link when you do, or @marick me. I'll be interested.

marick avatar Nov 21 '18 23:11 marick