Arrays with rigid variable

后端 未结 2 1011
轻奢々
轻奢々 2021-01-22 17:29

Well, I was doing a problem in which function I was using had a rigid variable. I had an idea of using arrays for that problem. So I thought of using arrays with same rigid vari

2条回答
  •  南笙
    南笙 (楼主)
    2021-01-22 18:24

    You're having trouble because the "inner" type signatures you've written out don't mean quite what they look like they'd mean. In particular, your uses of c do not correspond with one another not the a in the top signature and they must. Haskell is complaining that these "rigidly defined" type variables, despite being variables, cannot be the same, but since they're based on a "rigid" choice of what a is... they must!

    You can make GHC (but not Haskell in general) behave the way you'd like with an extension called {-# LANGUAGE ScopedTypeVariables #-} where your code becomes

    {-# LANGUAGE ScopedTypeVariables #-}
    
    rearrange :: forall a . [Int] -> [a] -> [a]
    rearrange l la = elems (f 1 posarr)
      where
        b = length l
        listarr :: Array Int Int
        listarr = listArray (1, b) l
        arra :: Array Int a
        arra = listArray (1,b) la
        posarr :: Array Int a
        posarr listArray (1,b) la
        f i posarr
          | (b < i) = posarr
          | otherwise = f (i+1) (posarr // [(listarr!i,arra!i)])
    

    Note that all I did was add the explicit forall and changed some c variables to a. What ScopedTypeVariables let you do is introduce type variable scopes using forall where any type signatures in code that is indented below such an explicitly forall'd signature can re-use the type variable names introduced in that forall and have them correspond exactly.

    Which might make more sense under examining how Haskell interprets type signatures without the extension. In particular, there is an implicit forall before every type signature

                                      -- is actually
    foo :: [a] -> [a] -> [a]          foo :: forall a. [a] -> [a] -> [a]
    foo xs ys = it where              foo xs ys = it where
      it :: [a]                         it :: forall a. [a]
      it = xs ++ ys                     it = xs ++ ys
    

    Which forces the a variable in each of these type signatures to be different and thus this fragment of code cannot compile because it is only valid if those two as are the same. With ScopedTypeVariables we have

    foo :: forall a . [a] -> [a] -> [a]
    foo xs ys = it where
      it :: [a]
      it = xs ++ ys
    

    where the inner signature's a is scoped to mean exactly the same a as in outer signature's.

提交回复
热议问题