{-# LANGUAGE FlexibleInstances #-} {- | Module : ELynx.Data.Tree.PhyloTree Description : Phylogenetic trees Copyright : (c) Dominik Schrempf 2019 License : GPL-3 Maintainer : dominik.schrempf@gmail.com Stability : unstable Portability : portable Creation date: Thu Jan 17 16:08:54 2019. Phylogenetic nodes have a branch length and a label. The easiest label type is 'Int': 'PhyloIntLabel'. Also, the 'L.ByteString' label is needed often: 'PhyloByteStringLabel'. XXX: This is all too complicated. Maybe I should just define a standard tree object like > data PhyloTree a = Tree (PhyloLabel a) and that's it. Forget about type classes like Measurable, Named and so on. -} module ELynx.Data.Tree.PhyloTree ( PhyloLabel (..) , PhyloIntLabel , PhyloByteStringLabel , removeBrLen ) where import qualified Data.ByteString.Lazy.Builder as L import qualified Data.ByteString.Lazy.Char8 as L import Data.Function import Data.Tree import Test.QuickCheck import ELynx.Data.Tree.BranchSupportTree import ELynx.Data.Tree.MeasurableTree import ELynx.Data.Tree.NamedTree -- | A primitive label type for phylogenetic trees with a name, possibly a -- branch support value, and a 'Double' branch length. data PhyloLabel a = PhyloLabel { pLabel :: a , pBrSup :: Maybe Double , pBrLen :: Double } deriving (Read, Show, Eq) instance Ord a => Ord (PhyloLabel a) where compare = compare `on` pLabel instance Measurable (PhyloLabel a) where getLen = pBrLen setLen l (PhyloLabel lbl s _) | l >= 0 = PhyloLabel lbl s l | otherwise = error "Branch lengths cannot be negative." instance BranchSupportLabel (PhyloLabel a) where getBranchSupport = pBrSup setBranchSupport Nothing l = l {pBrSup = Nothing} setBranchSupport (Just s) l | s > 0 = l {pBrSup = Just s} | otherwise = error "Branch support cannot be negative." instance Arbitrary a => Arbitrary (PhyloLabel a) where arbitrary = PhyloLabel <$> arbitrary <*> (Just <$> choose (0, 100)) <*> choose (0, 10) -- | Tree node with 'Int' label. type PhyloIntLabel = PhyloLabel Int instance Named PhyloIntLabel where getName = L.toLazyByteString . L.intDec . pLabel -- | Tree node with 'L.ByteString' label. Important for parsing -- 'ELynx.Import.Tree.Newick' files. type PhyloByteStringLabel = PhyloLabel L.ByteString instance Named PhyloByteStringLabel where getName = pLabel -- | Remove branch lengths from tree. removeBrLen :: Tree (PhyloLabel a) -> Tree a removeBrLen = fmap pLabel