Haskell monad chain type error

I am new to Haskell and I just follow the example of RWH. I am having problems with the following programs in chapter 14:

import qualified Data.Map as M type PersonName = String type PhoneNumber = String type BillingAddress = String data MobileCarrier = Honest_Bobs_Phone_Network | Morrisas_Marvelous_Mobiles | Petes_Plutocratic_Phones deriving (Eq, Ord) findCarrierBillingAddress :: PersonName -> M.Map PersonName PhoneNumber -> M.Map PhoneNumber MobileCarrier -> M.Map MobileCarrier BillingAddress -> Maybe BillingAddress -- This will work findCarrierBillingAddress person phoneMap carrierMap addressMap = do phone <- M.lookup person phoneMap carrier <- M.lookup phone carrierMap address <- M.lookup carrier addressMap return address -- This will NOT work: findCarrierBillingAddress person phoneMap carrierMap addressMap = return person >>= lookup phoneMap >>= lookup carrierMap >>= lookup addressMap where lookup = flip M.lookup 

It seems that when writing findCarrierBillingAddres in monad chain format using → =, it just doesn't print the check:

 /home/bruce/Programming/haskell/real/ch14/hello.hs:21:9: Couldn't match type `[Char]' with `MobileCarrier' Expected type: MobileCarrier -> Maybe BillingAddress Actual type: PersonName -> Maybe BillingAddress In the return type of a call of `lookup' In the second argument of `(>>=)', namely `lookup addressMap' In the expression: return person >>= lookup phoneMap >>= lookup carrierMap >>= lookup addressMap /home/bruce/Programming/haskell/real/ch14/hello.hs:21:16: Couldn't match type `MobileCarrier' with `[Char]' Expected type: M.Map PersonName BillingAddress Actual type: M.Map MobileCarrier BillingAddress In the first argument of `lookup', namely `addressMap' In the second argument of `(>>=)', namely `lookup addressMap' In the expression: return person >>= lookup phoneMap >>= lookup carrierMap >>= lookup addressMap Failed, modules loaded: none. 

The question is, why the second format using → = will not enter validation?

+4
source share
2 answers

This is simply a restriction of monomorphism, acting again. Since you have a template binding without a type signature, the intended type is monomorphic and therefore determined by the first use.

Just change it to

 lookup mk = flip M.lookup mk 

or even

 lookup m = flip M.lookup m 

You just need to convince the GHC to generalize the function, which it will not do when it is just a simple template binding. Adding a parameter turns it into a binding to a function, which means that it will be completely generalized.

If I lost you there a little, I wrote about it

+8
source

You fall into Monomorphism Constraint when an inferencer type tries to infer a type for your local lookup .

Instead of deriving the most general type, it determines from the first use of lookup that it must be of type lookup :: Map [Char] [Char] -> [Char] -> Maybe [Char] , which cannot be unified, when you then try to use it on the Map [Char] MobileCarrier .

Your first option is to disable monomorphism restriction using the pragma {-# LANGUAGE NoMonomorphismRestriction #-} . The second option is to add a lookup type signature as such

 findCarrierBillingAddress person phoneMap carrierMap addressMap = return person >>= lookup phoneMap >>= lookup carrierMap >>= lookup addressMap where lookup :: Ord k => M.Map ka -> k -> Maybe a lookup = flip M.lookup 
+7
source

Source: https://habr.com/ru/post/1494411/


All Articles