What is happening when I compose * with + in Haskell?

前端 未结 5 1244
臣服心动
臣服心动 2020-12-24 00:59

I\'m trying to understand the result of

(*) . (+) 

in Haskell. I know that the composition operator is just the standard composition of ma

5条回答
  •  情深已故
    2020-12-24 01:31

    Some extensions first:

    {-# LANGUAGE FlexibleContexts, FlexibleInstances, TypeSynonymInstances #-}
    

    As the other answers show, your function is

    weird :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
    weird x g = (x +) * g
    

    But this function does have non-weird semantics.

    There is a notion of difference lists. Accordingly, there is a notion of difference integers. I've seen them being used only in the dependently typed setting (e.g. here, but that's not the only case). The relevant part of the definition is

    instance Enum DiffInt where
        toEnum   n = (n +)
        fromEnum n = n 0
    
    instance Num DiffInt where
        n + m = n . m
        n * m = foldr (+) id $ replicate (fromEnum n) m
    

    This doesn't make much sense in Haskell, but can be useful with dependent types.

    Now we can write

    test :: DiffInt
    test = toEnum 3 * toEnum 4
    

    Or

    test :: DiffInt
    test = weird 3 (toEnum 4)
    

    In both the cases fromEnum test == 12.

    EDIT

    It's possible to avoid the using of the TypeSynonymInstances extension:

    {-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
    
    weird :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
    weird x g = (x +) * g
    
    instance (Enum a, Num a) => Enum (a -> a) where
        toEnum   n = (toEnum n +)
        fromEnum n = fromEnum $ n (toEnum 0)
    
    instance (Enum a, Num a) => Num (a -> a) where
        n + m = n . m
        n * m = foldr (+) id $ replicate (fromEnum n) m
    
    type DiffInt = Int -> Int
    

    As before we can write

    test' :: DiffInt
    test' = weird 3 (toEnum 4)
    

    But now we can also write

    -- difference ints over difference ints
    type DiffDiffInt = DiffInt -> DiffInt
    
    test'' :: DiffDiffInt
    test'' = weird (toEnum 3) (toEnum (toEnum 4))
    

    And

    main = print $ fromEnum $ fromEnum test'
    

    prints 12.

    EDIT2 Better links added.

提交回复
热议问题