Output Types Different Inside and Outside Block

Hi
I am working with the following block of code:

assembleMRSSWidget ∷ WidgetAssembler MRSSWidget
assembleMRSSWidget wid = do
  MediaRSS { media } ← useMediaRSS (MediaRSSKey "ccef7c")
  -- MediaRSS { media } ← useMediaRSS rssKey

-- 1. Test case: This outputs a string
  test ← case Array.index media 0 of
        Nothing → do
          pure ""
        Just (MediaRSSItem { url }) → do
          useURL url
          
  outputWidget' \aabb → mkEffectFn4 \doc parent tsl onE → do

    img ← imgEle aabb "" doc parent

    stopAt ← onFrameDuring (TimeSlice.actual tsl)
      { during: mkEffectFn2 \t' s@(Tuple i t) →
          if diffInst t' t >= Milliseconds 10000.0 then do
            let i' = (i + 1) `mod` Array.length media
                MediaRSSItem item =  fromMaybe (MediaRSSItem { url: "", duration: (Seconds 0.0), md5Checksum: "", fileSizeInBytes: 0.0, daysOld: (Days 0.0), fileType: ImageMediaFile })
                        (Array.index media i)
           
            -- 2. This is accepted as a valid string
            HTMLImageElement.setSrc (test) img

            -- 3. This is not accepted as a valid string
            HTMLImageElement.setSrc (useURL item.url) img
            pure (Tuple i' t')
          else
            pure s
      , end: mkEffectFn2 \_ _ → pure unit
      }
      (Tuple (1 `mod` Array.length media) bottom)
    

    pure stopAt

I labeled the comments of the trouble spots in this code.

  1. This is some test code that I wrote prior and it outputs a normal String
  2. If I try to pass it into setSrc it accepts because it is a normal string
  3. If I try to run useURL anywhere within outputWidget’ it instead errors saying:
Could not match type

    ValidatorT String (Tuple (CatList String) (Map AssemblerSource String))
      { contentKeyURLMap :: Map ContentKey
                              { cacheKey :: String
                              , cached :: Boolean
                              , etag :: String
                              , request :: ...
                              , url :: String
                              }
      , dataGridSourceMap :: Map DataGridKey
                               { etag :: String
                               , value :: DataGridSource
                               }
      , mediaRSSMap :: Map MediaRSSKey
                         { etag :: String
                         , value :: MediaRSS
                         }
      , textRSSDataMap :: Map TextRSSKey
                            { etag :: String
                            , value :: TextRSSData
                            }
      , timeZoneConverter :: { etag :: String
                             , value :: { fromUTC :: ...
                                        , incMaxYear :: Year
                                        , incMinYear :: Year
                                        , timeZone :: TimeZone
                                        , toUTC :: ...
                                        }
                             }
      , urlMap :: Map String
                    { cacheKey :: String
                    , cached :: Boolean
                    , etag :: String
                    , request :: ...
                    , url :: String
                    }
      , videoOverlappable :: Boolean
      , volume :: { etag :: String
                  , value :: Percent Number
                  }
      , weatherLayoutDataMap :: Map LocationId
                                  { etag :: String
                                  , value :: WeatherLayoutData
                                  }
      }
      Identity
      String

  with type

    String


while checking that type ValidatorT String (Tuple (CatList String) (Map AssemblerSource String))
                           { contentKeyURLMap :: Map ContentKey
                                                   { cacheKey :: String
                                                   , cached :: Boolean
                                                   , etag :: String
                                                   , request :: ...
                                                   , url :: String
                                                   }
                           , dataGridSourceMap :: Map DataGridKey
                                                    { etag :: String
                                                    , value :: DataGridSource
                                                    }
                           , mediaRSSMap :: Map MediaRSSKey
                                              { etag :: String
                                              , value :: MediaRSS
                                              }
                           , textRSSDataMap :: Map TextRSSKey
                                                 { etag :: String
                                                 , value :: TextRSSData
                                                 }
                           , timeZoneConverter :: { etag :: String
                                                  , value :: { fromUTC :: ...
                                                             , incMaxYear :: Year
                                                             , incMinYear :: Year
                                                             , timeZone :: TimeZone
                                                             , toUTC :: ...
                                                             }
                                                  }
                           , urlMap :: Map String
                                         { cacheKey :: String
                                         , cached :: Boolean
                                         , etag :: String
                                         , request :: ...
                                         , url :: String
                                         }
                           , videoOverlappable :: Boolean
                           , volume :: { etag :: String
                                       , value :: Percent Number
                                       }
                           , weatherLayoutDataMap :: Map LocationId
                                                       { etag :: String
                                                       , value :: WeatherLayoutData
                                                       }
                           }
                           Identity
                           String
  is at least as general as type String
while checking that expression useURL (item.url)
  has type String
in value declaration assembleMRSSWidget
PureScript(TypesDoNotUnify)

I dont understand why it is outputting a different type within the outputWidget block. Any help would be appreciated.
Thanks

Hi,

can we see the involved parts (useURL, outputWiget for example) somewhere?

EDIT: seems useUrl has some kind of effect so it should be something like m String (for some m) - that you bind in test <- ... useUrl url (note the <-) - in the second example you are not binding you - so you are using m String instead of String

Sure. Its going to be quite chunky and I dont even fully understand a lot of it since it is uncommented legacy code

outputWidget' ∷ WidgetAssembler (AABBPx → Slide')
outputWidget' f = pure \aabb _ → Slide (f aabb)
useURL ∷ String → Assembler String
useURL = useMap err _.urlMap AsmSrcURL au2r
  where
  err u = "Missing URL (" <> u <> ")."
type Slide' = 
  EffectFn4 HTMLDocument        -- Window Document
            HTMLElement         -- Parent Element
            TimeSlice           -- Parent TimeSlice
            PlaybackEvents      -- Raised playback events
            Stopper             -- stopAt
type WidgetAssembler a = a → Assembler WidgetSlide

Let me know if you need more

no it’s right there - useURL returns a Assembler String instead of a String - your first example binds the result of this effect to test

So if I try to bind within outputWidget it errors because it is an Effect. I just dont understand why it is okay with an Effect outside the block compared to within

test <- useURL url is syntactic sugar in the do-block - it uses the >>=-operator from Bind to chain effectful computations - aside from this useURL url is really just a Assembler String therefore the type-error if you try to use it in place of an String

AHHH. This sucks. The code is doing what I need it to do but without the useURL it is reaching out to the server for each image in the array rather than the downloaded images in the cache. Its so close but these stupid Effects are going to screw me over

WAIT WAIT WAIT. If I were to iterate through the array outside the outputWidget block, perform useURL on each elements url property then pass those values back into a new array, I could then use that array within output widget and circumvent the issue of having an effect within outputWidget, correct?

probably yes - I guess it makes sense to bring it all into a single Assembler-effect first (look at for)

1 Like

Thank you so much. It is now working properly. Oddly enough, “for” from Data.Traversable does not even show up as a recommended import when I type “for”. I would have literally never even known it existed if you had not mentioned it

glad I could help :wink:

1 Like