list - Haskell's head tail init and last in GHCi -
i have question head
, tail
, init
, last
. following works in ghci:
prelude data.list data.char> let n = [1..10] in (head n : tail n) [1,2,3,4,5,6,7,8,9,10]
as expected, whole list. should work init
, last
too, right?
prelude data.list data.char> let n = [1..10] in (init n : last n) <interactive>:39:1: non type-variable argument in constraint: enum [[a]] (use flexiblecontexts permit this) when checking ‘it’ has inferred type :: forall a. (enum a, enum [[a]], num a, num [[a]]) => [[a]]
if @ type signatures functions, head
, last
same -- both return element. init
, tail
same, because both return lists.
prelude data.list data.char> :info head head :: [a] -> -- defined in ‘ghc.list’ prelude data.list data.char> :info tail tail :: [a] -> [a] -- defined in ‘ghc.list’ prelude data.list data.char> :info init init :: [a] -> [a] -- defined in ‘ghc.list’ prelude data.list data.char> :info last last :: [a] -> -- defined in ‘ghc.list’
so non type-variable argument in constraint: enum [[a]]
mean? if init n
or last n
without construction of new list, [1..9]
, 10
.
it true head
/last
, tail
/init
have identical types. if had swapped out last
head
, init
tail
, have had no problem:
> let n = [1..10] in last n : init n [10,1,2,3,4,5,6,7,8,9]
but didn't. did both swap and another: changed order of arguments :
. happens :
doesn't take 2 arguments of same type:
> :t (:) (:) :: -> [a] -> [a]
so last swap not okay! in fact, if give n
more specific type signature, ghci give better error:
> let n :: [integer]; n = [1..10] in init n : last n <interactive>:1:50: couldn't match type ‘integer’ ‘[[integer]]’ expected type: [[[integer]]] actual type: [integer] in first argument of ‘last’, namely ‘n’ in second argument of ‘(:)’, namely ‘last n’
this error still not 100% clear, think bit of puzzling can see it's complaining about: since init n :: [integer]
, , (:) :: [integer] -> [[integer]] -> [[integer]]
, it's expecting last n :: [[integer]]
, therefore n :: [[[integer]]]
. explicitly said n :: [integer]
, conflict.
now, error gave in case? well, clue in type of [1..10]
:
> :t [1..10] [1..10] :: (enum t, num t) => [t]
notice [1..10]
polymorphic. moreover, used twice in expression, , can given separate monomorphic types in 2 uses. [1..10]
instantiated two different types in sequel!
now think can start see error got comes in. it's trying find type a
which:
enum a
-- needed..
part ofinit [1..10]
num a
-- needed1
,10
parts ofinit [1..10]
enum [[a]]
-- ifinit n :: a
, haveinit n : last n
well-typed, must havelast n :: [a]
, hence second occurrence ofn
must haven :: [[a]]
;enum
constraint needed..
part oflast [1..10]
num [[a]]
-- similar reasoning, needed1
,10
parts oflast [1..10]
but these constraints hard satisfy -- there's no instance of enum
, num
lists in scope in prelude
or data.list
. complains.
Comments
Post a Comment