infer-license-0.2.0: src/Data/License/Infer.hs
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE ViewPatterns #-}
module Data.License.Infer (
License(..)
, inferLicense
) where
import Control.Applicative
import Control.Monad
import Data.Foldable
import Data.Char
import Data.List
import Data.Ord (comparing)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Metrics
import Data.License.SpdxLicenses (licenses)
import Data.License.Type
inferLicense :: String -> Maybe License
inferLicense xs = inferLicenseByName xs <|> inferLicenseByLevenshtein xs
inferLicenseByName :: String -> Maybe License
inferLicenseByName (normalize -> xs) = asum $ map (matchName xs) licenseNames
matchName :: String -> (License, String) -> Maybe License
matchName xs (license, name) = license <$ guard (isPrefixOf name xs)
licenseNames :: [(License, String)]
licenseNames = map (fmap normalize) [
(GPLv2, "GNU GENERAL PUBLIC LICENSE Version 2, June 1991")
, (GPLv3, "GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007")
, (LGPLv2_1, "GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999")
, (LGPLv3, "GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007")
, (AGPLv3, "GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007")
, (MPL_2_0, "Mozilla Public License Version 2.0")
, (Apache_2_0, "Apache License Version 2.0, January 2004")
]
normalize :: String -> String
normalize = map toLower . filter isAlphaNum
inferLicenseByLevenshtein :: String -> Maybe License
inferLicenseByLevenshtein (T.pack -> xs)
| T.length xs > 2000 = Nothing
| otherwise = case maximumBy (comparing snd) (probabilities xs) of
(license, n) | n > 0.85 -> Just license
_ -> Nothing
probabilities :: Text -> [(License, Double)]
probabilities license = map (fmap probability) licenses
where
probability = realToFrac . levenshteinNorm license